From: heltai Date: Sun, 18 Aug 2013 16:48:15 +0000 (+0000) Subject: merged from trunk X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3cf012f784c1d15cd2b6c31955fb8905ccc8516d;p=dealii-svn.git merged from trunk git-svn-id: https://svn.dealii.org/branches/branch_manifold_id@30335 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/CMakeLists.txt b/deal.II/CMakeLists.txt index 04dba539c6..714613a8c7 100644 --- a/deal.II/CMakeLists.txt +++ b/deal.II/CMakeLists.txt @@ -49,7 +49,7 @@ FOREACH(_file ${_macro_files}) ENDFOREACH() # -# Check whether the doc and bundled folders are available: +# Check for the existence of various optional folders: # IF(EXISTS ${CMAKE_SOURCE_DIR}/bundled/CMakeLists.txt) SET(DEAL_II_HAVE_BUNDLED_DIRECTORY TRUE) @@ -59,6 +59,14 @@ IF(EXISTS ${CMAKE_SOURCE_DIR}/doc/CMakeLists.txt) SET(DEAL_II_HAVE_DOC_DIRECTORY TRUE) ENDIF() +IF(NOT DEFINED TEST_DIR) + GET_FILENAME_COMPONENT(TEST_DIR "${CMAKE_SOURCE_DIR}" PATH) + SET(TEST_DIR "${TEST_DIR}/tests") +ENDIF() +IF(EXISTS ${TEST_DIR}/CMakeLists.txt) + SET(DEAL_II_HAVE_TESTS_DIRECTORY TRUE) +ENDIF() + # # We have to initialize some cached variables before PROJECT is called, so # do it at this point: @@ -72,6 +80,8 @@ PROJECT(deal.II CXX) ENABLE_LANGUAGE_OPTIONAL(C) ENABLE_LANGUAGE_OPTIONAL(Fortran) +INCLUDE(setup_post_project_call) + INCLUDE(setup_deal_ii) INCLUDE(setup_compiler_flags) @@ -135,6 +145,10 @@ ADD_SUBDIRECTORY(cmake/config) # has to be included after source ADD_SUBDIRECTORY(contrib) # has to be included after source ADD_SUBDIRECTORY(examples) +IF(DEAL_II_HAVE_TESTS_DIRECTORY) + ADD_SUBDIRECTORY(${TEST_DIR} ${CMAKE_BINARY_DIR}/tests) +ENDIF() + # # And finally, print the configuration: # diff --git a/deal.II/bundled/CMakeLists.txt b/deal.II/bundled/CMakeLists.txt index 1e0d8a1e9b..846b614f2a 100644 --- a/deal.II/bundled/CMakeLists.txt +++ b/deal.II/bundled/CMakeLists.txt @@ -68,9 +68,10 @@ ENDIF() # # Threading Building Blocks library # -IF(NOT CMAKE_SYSTEM_NAME MATCHES "CYGWIN") +IF(NOT CMAKE_SYSTEM_NAME MATCHES "CYGWIN" + AND NOT CMAKE_SYSTEM_NAME MATCHES "Windows") # - # Cygwin is unsupported by tbb + # Cygwin is unsupported by tbb, Windows due to the way we compile tbb... # SET(FEATURE_THREADS_HAVE_BUNDLED TRUE) OPTION(DEAL_II_FORCE_BUNDLED_THREADS diff --git a/deal.II/bundled/boost-1.49.0/include/boost/signals2/detail/foreign_ptr.hpp b/deal.II/bundled/boost-1.49.0/include/boost/signals2/detail/foreign_ptr.hpp index 3e2357b8e8..2e7be17839 100644 --- a/deal.II/bundled/boost-1.49.0/include/boost/signals2/detail/foreign_ptr.hpp +++ b/deal.II/bundled/boost-1.49.0/include/boost/signals2/detail/foreign_ptr.hpp @@ -18,14 +18,6 @@ #include #include -#if !defined(BOOST_INTEL_STDCXX0X) -namespace std -{ - template class shared_ptr; - template class weak_ptr; -} -#endif - namespace boost { template class shared_ptr; @@ -39,10 +31,20 @@ namespace boost { typedef boost::shared_ptr shared_type; }; + +// Workaround for a bug in boost: +// https://svn.boost.org/trac/boost/ticket/6655 +// +// It should be safe to depend on DEAL macros at this point as this header +// should only be used by deal.II and dependent projects... +// +// - Maier, 2013 +#ifdef DEAL_II_CAN_USE_CXX11 template struct weak_ptr_traits > { typedef std::shared_ptr shared_type; }; +#endif template struct shared_ptr_traits {}; @@ -51,10 +53,13 @@ namespace boost { typedef boost::weak_ptr weak_type; }; +// as above +#ifdef DEAL_II_CAN_USE_CXX11 template struct shared_ptr_traits > { typedef std::weak_ptr weak_type; }; +#endif namespace detail { diff --git a/deal.II/cmake/checks/check_01_cpu_features.cmake b/deal.II/cmake/checks/check_01_cpu_features.cmake index d8c275b578..9639b89497 100644 --- a/deal.II/cmake/checks/check_01_cpu_features.cmake +++ b/deal.II/cmake/checks/check_01_cpu_features.cmake @@ -41,23 +41,19 @@ # IF(CMAKE_C_COMPILER_WORKS) INCLUDE(TestBigEndian) + + CLEAR_CMAKE_REQUIRED() TEST_BIG_ENDIAN(DEAL_II_WORDS_BIGENDIAN) + RESET_CMAKE_REQUIRED() ELSE() MESSAGE(STATUS "No suitable C compiler was found! Assuming little endian platform." ) + SET(DEAL_II_WORDS_BIGENDIAN "0") ENDIF() IF(DEAL_II_ALLOW_PLATFORM_INTROSPECTION) - - # - # These tests depend on certain cpu instruction sets being enabled, so - # use the user supplied compiler flags for the tests as well: - # - SET(CMAKE_REQUIRED_FLAGS "${CMAKE_CXX_FLAGS_SAVED}") - - # # Take care that the following tests are rerun if CMAKE_REQUIRED_FLAGS # changes.. @@ -143,10 +139,9 @@ IF(DEAL_II_ALLOW_PLATFORM_INTROSPECTION) } " DEAL_II_HAVE_AVX) - - SET(CMAKE_REQUIRED_FLAGS "") ENDIF() + IF(DEAL_II_HAVE_SSE2) IF(DEAL_II_HAVE_AVX) SET(DEAL_II_COMPILER_VECTORIZATION_LEVEL 2) @@ -156,4 +151,3 @@ IF(DEAL_II_HAVE_SSE2) ELSE() SET(DEAL_II_COMPILER_VECTORIZATION_LEVEL 0) ENDIF() - diff --git a/deal.II/cmake/checks/check_02_system_features.cmake b/deal.II/cmake/checks/check_02_system_features.cmake index 25d54167f5..22e6a8a88b 100644 --- a/deal.II/cmake/checks/check_02_system_features.cmake +++ b/deal.II/cmake/checks/check_02_system_features.cmake @@ -68,9 +68,9 @@ SWITCH_LIBRARY_PREFERENCE() MARK_AS_ADVANCED(m_LIBRARY) IF(NOT m_LIBRARY MATCHES "-NOTFOUND") - SET(CMAKE_REQUIRED_LIBRARIES ${m_LIBRARY}) + LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${m_LIBRARY}) CHECK_CXX_SYMBOL_EXISTS("jn" "math.h" HAVE_JN) - SET(CMAKE_REQUIRED_LIBRARIES) + RESET_CMAKE_REQUIRED() IF(HAVE_JN) LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${m_LIBRARY}) ENDIF() @@ -116,12 +116,32 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Windows") SET(DEAL_II_MSVC TRUE) # - # Disable shared libraries on native Windows targets for the moment. + # Shared library handling: # - MESSAGE(WARNING "\n" - "BUILD_SHARED_LIBS forced to OFF\n\n" - ) - SET(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # + # With MinGW we're lucky: + # + ENABLE_IF_LINKS(DEAL_II_LINKER_FLAGS "-Wl,--export-all-symbols") + ENABLE_IF_LINKS(DEAL_II_LINKER_FLAGS "-Wl,--enable-auto-import") + ENABLE_IF_LINKS(DEAL_II_LINKER_FLAGS "-Wl,--allow-multiple-definition") + + # + # Workaround for a miscompilation and linkage issue with shared libraries + # with MinGW. Replacing -O0 with -O1 seems to help.. + # + REPLACE_FLAG(DEAL_II_CXX_FLAGS_DEBUG "-O0" "-O1") + + ELSE() + + # + # Otherwise disable shared libraries: + # + MESSAGE(WARNING "\n" + "BUILD_SHARED_LIBS forced to OFF\n\n" + ) + SET(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + ENDIF() # # Disable -ggdb and -g on Windows/MinGW targets for the moment until the @@ -135,6 +155,7 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Windows") STRIP_FLAG(DEAL_II_LINKER_FLAGS_DEBUG "-g") ENDIF() + IF(CMAKE_SYSTEM_NAME MATCHES "CYGWIN") # # Workaround for a miscompilation and linkage issue with shared libraries @@ -143,5 +164,4 @@ IF(CMAKE_SYSTEM_NAME MATCHES "CYGWIN") # - Matthias Maier, 2013 # REPLACE_FLAG(DEAL_II_CXX_FLAGS_DEBUG "-O0" "-O1") - ENDIF() diff --git a/deal.II/cmake/checks/check_03_compiler_bugs.cmake b/deal.II/cmake/checks/check_03_compiler_bugs.cmake index cf49fb0e57..bb63ba0740 100644 --- a/deal.II/cmake/checks/check_03_compiler_bugs.cmake +++ b/deal.II/cmake/checks/check_03_compiler_bugs.cmake @@ -21,43 +21,6 @@ ######################################################################## -# -# Some compiler versions, notably ICC, have trouble with the -# following code in which we explicitly call a destructor. -# This has to be worked around with a typedef. The problem is -# that the workaround fails with some other compilers, so that -# we can not unconditionally use the workaround... -# -# - Wolfgang Bangerth, Matthias Maier, rewritten 2012 -# -CHECK_CXX_COMPILER_BUG( - " - namespace dealii - { - namespace FEValuesViews - { - template struct Scalar {}; - } - - template - struct X - { - FEValuesViews::Scalar scalars[dim*spacedim]; - - void f() - { - scalars[0].dealii::FEValuesViews::Scalar::~Scalar (); - } - }; - - template struct X<2,2>; - } - int main() { return 0; } - " - DEAL_II_EXPLICIT_DESTRUCTOR_BUG - ) - - # # On some gcc 4.3 snapshots, a 'const' qualifier on a return type triggers a # warning. This is unfortunate, since we happen to stumble on this diff --git a/deal.II/cmake/config/CMakeLists.txt b/deal.II/cmake/config/CMakeLists.txt index 037af96e8c..071ba6110b 100644 --- a/deal.II/cmake/config/CMakeLists.txt +++ b/deal.II/cmake/config/CMakeLists.txt @@ -81,7 +81,7 @@ FOREACH(_build ${DEAL_II_BUILD_TYPES}) ) LIST(APPEND CONFIG_LIBRARIES ${_keyword} - ${CONFIG_LIBRARIES_${_build}} + \${DEAL_II_LIBRARIES_${_build}} ) SET(CONFIG_TARGET_${_build} @@ -89,7 +89,7 @@ FOREACH(_build ${DEAL_II_BUILD_TYPES}) ) LIST(APPEND CONFIG_TARGET ${_keyword} - ${DEAL_II_BASE_NAME}${DEAL_II_${_build}_SUFFIX} + \${DEAL_II_TARGET_${_build}} ) ENDFOREACH() diff --git a/deal.II/cmake/config/Make.global_options.in b/deal.II/cmake/config/Make.global_options.in index bcedebb257..a32109a464 100644 --- a/deal.II/cmake/config/Make.global_options.in +++ b/deal.II/cmake/config/Make.global_options.in @@ -1,22 +1,28 @@ -# $Id$ - -# -# Compatibility Make.global_options file -# - -############################################################################### -## Please note: +## --------------------------------------------------------------------- +## $Id$ +## +## Copyright (C) 2012 - 2013 by the deal.II authors ## -## This is a compatibility Make.global_options file generated by CMake -## from the ./cmake/config/Make.global_options.in file. +## This file is part of the deal.II library. ## -############################################################################### +## The deal.II library is free software; you can use it, redistribute +## 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. +## The full text of the license can be found in the file LICENSE at +## the top level of the deal.II distribution. +## +## --------------------------------------------------------------------- # -# the following lines will be replaced by cmake +# Please note: +# +# This is a compatibility Make.global_options file generated by CMake +# from the ./cmake/config/Make.global_options.in file. # + D = @CMAKE_INSTALL_PREFIX@ CXX = @CMAKE_CXX_COMPILER@ CXX-ID = @CMAKE_CXX_COMPILER_ID@ @@ -62,15 +68,12 @@ EXEEXT = # set paths to all the libraries we need: -lib-deal2.o = ${MAKEFILE_TARGETS_RELEASE} -lib-deal2.g = ${MAKEFILE_TARGETS_DEBUG} +lib-deal2.o = @MAKEFILE_TARGETS_RELEASE@ +lib-deal2.g = @MAKEFILE_TARGETS_DEBUG@ -# include paths as command line flags. while compilers allow a space between -# the '-I' and the actual path, we also send these flags to the -# make_dependencies program that doesn't support the extra space. -# -INCLUDE = ${MAKEFILE_INCLUDE_DIRS} +# Include paths as command line flags +INCLUDE = @MAKEFILE_INCLUDE_DIRS@ # compiler flags for debug and optimized mode diff --git a/deal.II/cmake/configure/configure_1_lapack.cmake b/deal.II/cmake/configure/configure_1_lapack.cmake index a319fe155b..455a4944b4 100644 --- a/deal.II/cmake/configure/configure_1_lapack.cmake +++ b/deal.II/cmake/configure/configure_1_lapack.cmake @@ -19,64 +19,9 @@ # MACRO(FEATURE_LAPACK_FIND_EXTERNAL var) - FIND_PACKAGE(LAPACK) - - # - # So, well... LAPACK_LINKER_FLAGS and LAPACK_LIBRARIES should contain the - # complete link interface. But for invalid user overrides we include - # BLAS_LIBRARIES and BLAS_LINKER_FLAGS as well.. - # - IF(NOT LAPACK_LINKER_FLAGS MATCHES "${BLAS_LINKER_FLAGS}") - MESSAGE(STATUS - "Manually adding BLAS_LINKER_FLAGS to LAPACK_LINKER_FLAGS" - ) - ADD_FLAGS(LAPACK_LINKER_FLAGS "${BLAS_LINKER_FLAGS}") - ENDIF() - IF(NOT "${LAPACK_LIBRARIES}" MATCHES "${BLAS_LIBRARIES}") - MESSAGE(STATUS - "Manually adding BLAS_LIBRARIES to LAPACK_LIBRARIES" - ) - LIST(APPEND LAPACK_LIBRARIES ${BLAS_LIBRARIES}) - ENDIF() - - MARK_AS_ADVANCED( - atlas_LIBRARY - blas_LIBRARY - gslcblas_LIBRARY - lapack_LIBRARY - m_LIBRARY - ptf77blas_LIBRARY - ptlapack_LIBRARY - refblas_LIBRARY - reflapack_LIBRARY - ) + FIND_PACKAGE(DEALII_LAPACK) IF(LAPACK_FOUND) - # - # Well, in case of static archives we have to manually pick up the - # complete link interface. *sigh* - # - # Do this unconditionally for the most common case: - # TODO: Non-GNU setups... - # - # - # Switch the library preference back to prefer dynamic libraries if - # DEAL_II_PREFER_STATIC_LIBS=TRUE but DEAL_II_STATIC_EXECUTABLE=FALSE. In - # this case system libraries should be linked dynamically. - # - SWITCH_LIBRARY_PREFERENCE() - FOREACH(_lib gfortran m quadmath) - FIND_LIBRARY(${_lib}_LIBRARY - NAMES ${_lib} - HINTS ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) - MARK_AS_ADVANCED(${_lib}_LIBRARY) - - IF(NOT ${_lib}_LIBRARY MATCHES "-NOTFOUND") - LIST(APPEND LAPACK_LIBRARIES ${${_lib}_LIBRARY}) - ENDIF() - ENDFOREACH() - SWITCH_LIBRARY_PREFERENCE() - SET(${var} TRUE) ENDIF() ENDMACRO() @@ -97,8 +42,12 @@ SET(DEAL_II_LAPACK_FUNCTIONS ) MACRO(CHECK_FOR_LAPACK_FUNCTIONS) + # + # Clear the test flags because the following test will use a C compiler + # + CLEAR_CMAKE_REQUIRED() + SET(CMAKE_REQUIRED_FLAGS "${LAPACK_LINKER_FLAGS}") SET(CMAKE_REQUIRED_LIBRARIES ${LAPACK_LIBRARIES}) - ADD_FLAGS(CMAKE_REQUIRED_FLAGS "${LAPACK_LINKER_FLAGS}") # # Push -pthread as well: # @@ -118,9 +67,7 @@ MACRO(CHECK_FOR_LAPACK_FUNCTIONS) ENDFOREACH() ENDIF() - SET(CMAKE_REQUIRED_LIBRARIES) - STRIP_FLAG(CMAKE_REQUIRED_FLAGS "${LAPACK_LINKER_FLAGS}") - STRIP_FLAG(CMAKE_REQUIRED_FLAGS "-pthread") + RESET_CMAKE_REQUIRED() ENDMACRO() diff --git a/deal.II/cmake/configure/configure_1_mpi.cmake b/deal.II/cmake/configure/configure_1_mpi.cmake index 85de2a41c2..2eb6bd3847 100644 --- a/deal.II/cmake/configure/configure_1_mpi.cmake +++ b/deal.II/cmake/configure/configure_1_mpi.cmake @@ -107,10 +107,15 @@ MACRO(FEATURE_MPI_ERROR_MESSAGE) MESSAGE(FATAL_ERROR "\n" "Could not find any suitable mpi library!\n" "Please ensure that an mpi library is installed on your computer\n" - "and set CMAKE_CXX_COMPILER and CMAKE_C_COMPILER to the appropriate mpi\n" - "wrappers:\n" - " $ CC=\".../mpicc\" CXX=\".../mpicxx\" cmake <...>\n" - " $ cmake -DCMAKE_C_COMPILER=\".../mpicc\" -DCMAKE_CXX_COMPIER=\".../mpicxx\" <...>\n" + "and set CMAKE_CXX_COMPILER to the appropriate mpi wrappers:\n" + " $ CXX=\".../mpicxx\" cmake <...>\n" + " $ cmake -DCMAKE_CXX_COMPILER=\".../mpicxx\" <...>\n" + "Or with additional C and Fortran wrappers (recommended!):\n" + " $ CC=\".../mpicc\" CXX=\".../mpicxx\" F90=\".../mpif90\" cmake <...>\n" + " $ cmake -DCMAKE_C_COMPILER=\".../mpicc\"\\\n" + " -DCMAKE_CXX_COMPILER=\".../mpicxx\"\\\n" + " -DCMAKE_Fortran_COMPILER=\".../mpif90\"\\\n" + " <...>\n" ) ENDMACRO() diff --git a/deal.II/cmake/configure/configure_1_threads.cmake b/deal.II/cmake/configure/configure_1_threads.cmake index 8525ad770e..d43fd3ea49 100644 --- a/deal.II/cmake/configure/configure_1_threads.cmake +++ b/deal.II/cmake/configure/configure_1_threads.cmake @@ -36,7 +36,15 @@ MACRO(SETUP_THREADING) # this case system libraries should be linked dynamically. # SWITCH_LIBRARY_PREFERENCE() + + # + # Clear the test flags because FindThreads.cmake will use a C compiler: + # + CLEAR_CMAKE_REQUIRED() + FIND_PACKAGE(Threads) + + RESET_CMAKE_REQUIRED() SWITCH_LIBRARY_PREFERENCE() ELSE() @@ -112,7 +120,7 @@ MACRO(SETUP_THREADING) } " DEAL_II_HAVE_MT_POSIX_BARRIERS) - STRIP_FLAG(CMAKE_REQUIRED_FLAGS "${CMAKE_THREAD_LIBS_INIT}") + RESET_CMAKE_REQUIRED() IF(NOT DEAL_II_HAVE_MT_POSIX_BARRIERS) SET(DEAL_II_USE_MT_POSIX_NO_BARRIERS TRUE) ENDIF() diff --git a/deal.II/cmake/configure/configure_2_metis.cmake b/deal.II/cmake/configure/configure_2_metis.cmake index 92a1f10880..8d83b9661d 100644 --- a/deal.II/cmake/configure/configure_2_metis.cmake +++ b/deal.II/cmake/configure/configure_2_metis.cmake @@ -22,7 +22,7 @@ MACRO(FEATURE_METIS_FIND_EXTERNAL var) FIND_PACKAGE(METIS) IF(METIS_FOUND) - IF(METIS_MAJOR GREATER 4) + IF(METIS_VERSION_MAJOR GREATER 4) SET(${var} TRUE) ELSE() MESSAGE(STATUS "Insufficient metis installation found: " diff --git a/deal.II/cmake/configure/configure_2_trilinos.cmake b/deal.II/cmake/configure/configure_2_trilinos.cmake index 41a5f93bf5..3669492796 100644 --- a/deal.II/cmake/configure/configure_2_trilinos.cmake +++ b/deal.II/cmake/configure/configure_2_trilinos.cmake @@ -131,10 +131,10 @@ MACRO(FEATURE_TRILINOS_FIND_EXTERNAL var) "has to be configured to use the same number of bits as deal.II, but " "found:\n" " DEAL_II_WITH_64BIT_INDICES = ${DEAL_II_WITH_64BIT_INDICES}\n" - " TRILINOS_WITH_NO_32BIT_INDICES = ${TRILINOS_WITH_NO_32_BIT_INDICES}\n" + " TRILINOS_WITH_NO_32BIT_INDICES = ${TRILINOS_WITH_NO_32_BIT_INDICES}\n" ) SET(${var} FALSE) - ENDIF() + ENDIF() # # Trilinos has to be configured with 64bit indices if deal.II uses unsigned long @@ -143,74 +143,41 @@ MACRO(FEATURE_TRILINOS_FIND_EXTERNAL var) IF(TRILINOS_WITH_NO_64BIT_INDICES AND DEAL_II_WITH_64BIT_INDICES) MESSAGE(STATUS "deal.II was configured to use 64bit global indices but " "Trilinos was not." - ) + ) SET(TRILINOS_ADDITIONAL_ERROR_STRING ${TRILINOS_ADDITIONAL_ERROR_STRING} "The Trilinos installation (found at \"${TRILINOS_DIR}\")\n" "has to be configured to use the same number of bits as deal.II, but " "found:\n" " DEAL_II_WITH_64BIT_INDICES = ${DEAL_II_WITH_64BIT_INDICES}\n" - " TRILINOS_WITH_NO_64BIT_INDICES = ${TRILINOS_WITH_NO_64_BIT_INDICES}\n" + " TRILINOS_WITH_NO_64BIT_INDICES = ${TRILINOS_WITH_NO_64_BIT_INDICES}\n" ) SET(${var} FALSE) - ENDIF() - + ENDIF() # # Some versions of Sacado_cmath.hpp do things that aren't compatible # with the -std=c++0x flag of GCC, see deal.II FAQ. # Test whether that is indeed the case # - IF(${var}) - SET(CMAKE_REQUIRED_INCLUDES ${TRILINOS_INCLUDE_DIRS}) - PUSH_TEST_FLAG("${DEAL_II_CXX11_FLAG}") - - CHECK_CXX_SOURCE_COMPILES( - " - #include - int main(){ return 0; } - " - TRILINOS_SUPPORTS_CPP11) - - IF(DEAL_II_CAN_USE_CXX11 AND NOT TRILINOS_SUPPORTS_CPP11) - # - # Try whether exporting HAS_C99_TR1_CMATH helps: - # - PUSH_TEST_FLAG("-DHAS_C99_TR1_CMATH") - CHECK_CXX_SOURCE_COMPILES( - " - #include - int main(){ return 0; } - " - TRILINOS_HAS_C99_TR1_WORKAROUND) - POP_TEST_FLAG() - - IF(TRILINOS_HAS_C99_TR1_WORKAROUND) - LIST(APPEND DEAL_II_DEFINITIONS "HAS_C99_TR1_CMATH") - LIST(APPEND DEAL_II_USER_DEFINITIONS "HAS_C99_TR1_CMATH") - ELSE() - MESSAGE(STATUS "Could not find a sufficient Trilinos installation: " - "The installation is not compatible with the C++ standard selected for " - "this compiler." - ) - SET(TRILINOS_ADDITIONAL_ERROR_STRING - ${TRILINOS_ADDITIONAL_ERROR_STRING} - "The Trilinos installation (found at \"${TRILINOS_DIR}\")\n" - "is not compatible with the C++ standard selected for\n" - "this compiler. See the deal.II FAQ page for a solution.\n\n" - ) - SET(${var} FALSE) - ENDIF() - ENDIF() + IF(DEAL_II_CAN_USE_CXX11 AND NOT TRILINOS_SUPPORTS_CPP11) - POP_TEST_FLAG() - SET(CMAKE_REQUIRED_INCLUDES) - - # - # Remove the following variables from the cache to force a recheck: - # - UNSET(TRILINOS_SUPPORTS_CPP11 CACHE) - UNSET(TRILINOS_HAS_C99_TR1_WORKAROUND CACHE) + IF(TRILINOS_HAS_C99_TR1_WORKAROUND) + LIST(APPEND DEAL_II_DEFINITIONS "HAS_C99_TR1_CMATH") + LIST(APPEND DEAL_II_USER_DEFINITIONS "HAS_C99_TR1_CMATH") + ELSE() + MESSAGE(STATUS "Could not find a sufficient Trilinos installation: " + "The installation is not compatible with the C++ standard selected for " + "this compiler." + ) + SET(TRILINOS_ADDITIONAL_ERROR_STRING + ${TRILINOS_ADDITIONAL_ERROR_STRING} + "The Trilinos installation (found at \"${TRILINOS_DIR}\")\n" + "is not compatible with the C++ standard selected for\n" + "this compiler. See the deal.II FAQ page for a solution.\n\n" + ) + SET(${var} FALSE) + ENDIF() ENDIF() ENDIF(TRILINOS_FOUND) @@ -218,13 +185,6 @@ ENDMACRO() MACRO(FEATURE_TRILINOS_CONFIGURE_EXTERNAL) - # - # *Boy* Sanitize the include paths given by TrilinosConfig.cmake... - # - STRING(REGEX REPLACE - "(lib64|lib)\\/cmake\\/Trilinos\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/" "" - TRILINOS_INCLUDE_DIRS "${TRILINOS_INCLUDE_DIRS}" - ) INCLUDE_DIRECTORIES(${TRILINOS_INCLUDE_DIRS}) diff --git a/deal.II/cmake/configure/configure_boost.cmake b/deal.II/cmake/configure/configure_boost.cmake index 7d017236b4..f2071971ea 100644 --- a/deal.II/cmake/configure/configure_boost.cmake +++ b/deal.II/cmake/configure/configure_boost.cmake @@ -38,6 +38,11 @@ SET(DEAL_II_WITH_BOOST ON # Always true. We need it :-] MACRO(FEATURE_BOOST_FIND_EXTERNAL var) + SET_IF_EMPTY(BOOST_DIR "$ENV{BOOST_DIR}") + IF(NOT "${BOOST_DIR}" STREQUAL "") + SET(BOOST_ROOT "${BOOST_DIR}") + ENDIF() + IF(DEAL_II_WITH_THREADS) SET(_boost_components serialization system thread) ELSE() @@ -65,11 +70,24 @@ MACRO(FEATURE_BOOST_FIND_EXTERNAL var) MARK_AS_ADVANCED(Boost_DIR) + SET(BOOST_VERSION_MAJOR "${Boost_MAJOR_VERSION}") + SET(BOOST_VERSION_MINOR "${Boost_MINOR_VERSION}") + SET(BOOST_VERSION_SUBMINOR "${Boost_SUBMINOR_VERSION}") + SET(BOOST_VERSION + "${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_SUBMINOR}" + ) + + IF( Boost_SERIALIZATION_FOUND AND Boost_SYSTEM_FOUND AND (NOT DEAL_II_WITH_THREADS OR Boost_THREAD_FOUND) ) + MARK_AS_ADVANCED(BOOST_DIR) SET(${var} TRUE) + ELSE() + SET(BOOST_DIR "" CACHE PATH + "An optional hint to a boost directory" + ) ENDIF() ENDMACRO() diff --git a/deal.II/cmake/configure/configure_slepc.cmake b/deal.II/cmake/configure/configure_slepc.cmake index 269f85daa1..c0d1b212b0 100644 --- a/deal.II/cmake/configure/configure_slepc.cmake +++ b/deal.II/cmake/configure/configure_slepc.cmake @@ -25,9 +25,14 @@ MACRO(FEATURE_SLEPC_FIND_EXTERNAL var) IF(SLEPC_FOUND) # - # Check whether SLEPc and PETSc are compatible. + # Check whether SLEPc and PETSc are compatible according to + # SLEPc's rules: This is equivalent to asking if the VERSION_MAJOR + # and VERSION_MINOR of PETSc and SLEPc are + # equivalent; and where VERSION_SUBMINORs are allowed to differ. # - IF("${SLEPC_VERSION}" STREQUAL "${PETSC_VERSION}") + IF( ("${SLEPC_VERSION_MAJOR}" STREQUAL "${PETSC_VERSION_MAJOR}") + AND + ("${SLEPC_VERSION_MINOR}" STREQUAL "${PETSC_VERSION_MINOR}")) SET(${var} TRUE) ELSE() diff --git a/deal.II/cmake/macros/macro_clear_cmake_required.cmake b/deal.II/cmake/macros/macro_clear_cmake_required.cmake new file mode 100644 index 0000000000..186004f5d0 --- /dev/null +++ b/deal.II/cmake/macros/macro_clear_cmake_required.cmake @@ -0,0 +1,29 @@ +## --------------------------------------------------------------------- +## $Id$ +## +## Copyright (C) 2013 by the deal.II authors +## +## This file is part of the deal.II library. +## +## The deal.II library is free software; you can use it, redistribute +## 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. +## The full text of the license can be found in the file LICENSE at +## the top level of the deal.II distribution. +## +## --------------------------------------------------------------------- + +# +# A small macro to clear the CMAKE_REQUIRED_* variables. +# +# Usage: +# CLEAR_CMAKE_REQUIRED_FLAGS +# + +MACRO(CLEAR_CMAKE_REQUIRED) + SET(CMAKE_REQUIRED_FLAGS) + SET(CMAKE_REQUIRED_INCLUDES) + SET(CMAKE_REQUIRED_LIBRARIES) +ENDMACRO() + diff --git a/deal.II/cmake/macros/macro_deal_ii_initialize_cached_variables.cmake b/deal.II/cmake/macros/macro_deal_ii_initialize_cached_variables.cmake index bcd842eb09..8f355ff1c9 100644 --- a/deal.II/cmake/macros/macro_deal_ii_initialize_cached_variables.cmake +++ b/deal.II/cmake/macros/macro_deal_ii_initialize_cached_variables.cmake @@ -51,9 +51,15 @@ MACRO(DEAL_II_INITIALIZE_CACHED_VARIABLES) ENDIF() # - # Reset build type if unsupported: + # Reset build type if unsupported, i.e. if it is not (case insensitively + # equal to Debug or Release or unsupported by the current build type: # - IF(NOT DEAL_II_BUILD_TYPE MATCHES "${CMAKE_BUILD_TYPE}") + STRING(TOLOWER "${CMAKE_BUILD_TYPE}" _cmake_build_type) + STRING(TOLOWER "${DEAL_II_BUILD_TYPE}" _deal_ii_build_type) + + IF( NOT "${_cmake_build_type}" MATCHES "^(debug|release)$" + OR NOT _deal_ii_build_type MATCHES "${_cmake_build_type}" ) + IF("${DEAL_II_BUILD_TYPE}" STREQUAL "DebugRelease") SET(_new_build_type "Debug") ELSE() diff --git a/deal.II/cmake/macros/macro_deal_ii_setup_target.cmake b/deal.II/cmake/macros/macro_deal_ii_setup_target.cmake index e98bd25576..28b88dd1d0 100644 --- a/deal.II/cmake/macros/macro_deal_ii_setup_target.cmake +++ b/deal.II/cmake/macros/macro_deal_ii_setup_target.cmake @@ -61,16 +61,16 @@ MACRO(DEAL_II_SETUP_TARGET _target) ) # - # Append build type dependend flags and definitions. + # Append build type dependent flags and definitions. # # # For this we obey the behaviour of the "optimized" and "debug" # keywords and this is a bit tricky: # - # If the global property DEBUG_CONFIGURATIONS is set all build - # types that (case insensitive) match one of the listed build types is - # considered a "debug" build. The rest is "optimized". + # If the global property DEBUG_CONFIGURATIONS is set all build types that + # (case insensitively) match one of the listed build types is considered + # a "debug" build. The rest is "optimized". # # Otherwise every build type that (case insensitively) matches "debug" is # considered a debug build. @@ -97,7 +97,12 @@ MACRO(DEAL_II_SETUP_TARGET _target) ENDIF() ENDIF() - IF(_on_debug_build) + # + # We can only append DEBUG link flags and compile definitions if deal.II + # was build with Debug or DebugRelease build type. So test for this: + # + IF( _on_debug_build + AND DEAL_II_BUILD_TYPE MATCHES "Debug" ) SET_PROPERTY(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS " ${DEAL_II_LINKER_FLAGS_DEBUG}" ) diff --git a/deal.II/cmake/macros/macro_enable_if_links.cmake b/deal.II/cmake/macros/macro_enable_if_links.cmake index 0f4ef07e96..6c2bfeb6d1 100644 --- a/deal.II/cmake/macros/macro_enable_if_links.cmake +++ b/deal.II/cmake/macros/macro_enable_if_links.cmake @@ -30,7 +30,7 @@ MACRO(ENABLE_IF_LINKS _variable _flag) STRING(REPLACE "," "" _flag_name "${_flag_name}") STRING(REPLACE "--" "__" _flag_name "${_flag_name}") SET(_backup ${CMAKE_REQUIRED_LIBRARIES}) - SET(CMAKE_REQUIRED_LIBRARIES "${_flag_stripped}") + LIST(APPEND CMAKE_REQUIRED_LIBRARIES "${_flag_stripped}") CHECK_CXX_COMPILER_FLAG( "" DEAL_II_HAVE_FLAG_${_flag_name} diff --git a/deal.II/cmake/macros/macro_enable_language_optional.cmake b/deal.II/cmake/macros/macro_enable_language_optional.cmake index 885b960f8c..fccb978ae4 100644 --- a/deal.II/cmake/macros/macro_enable_language_optional.cmake +++ b/deal.II/cmake/macros/macro_enable_language_optional.cmake @@ -32,10 +32,10 @@ # MACRO(ENABLE_LANGUAGE_OPTIONAL _language) - # - # Run this check exactly once: - # IF(NOT ${_language}_CHECKED) + # + # Run this check exactly once: + # SET(${_language}_CHECKED TRUE CACHE INTERNAL "" FORCE) SET(_tmp ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/${_language}_test) @@ -58,9 +58,17 @@ MACRO(ENABLE_LANGUAGE_OPTIONAL _language) ) IF("${_result}" STREQUAL "0") + SET(DEAL_II_${_language}_COMPILER_WORKS TRUE CACHE INTERNAL "" FORCE) ENABLE_LANGUAGE(${_language}) ELSE() MESSAGE(STATUS "No working ${_language} compiler found, disabling ${_language}") ENDIF() + ELSE() + # + # Enable the language depending on the cached result from a former run: + # + IF(DEAL_II_${_language}_COMPILER_WORKS) + ENABLE_LANGUAGE(${_language}) + ENDIF() ENDIF() ENDMACRO() diff --git a/deal.II/cmake/macros/macro_reset_cmake_required.cmake b/deal.II/cmake/macros/macro_reset_cmake_required.cmake new file mode 100644 index 0000000000..0f2865a3d7 --- /dev/null +++ b/deal.II/cmake/macros/macro_reset_cmake_required.cmake @@ -0,0 +1,30 @@ +## --------------------------------------------------------------------- +## $Id$ +## +## Copyright (C) 2013 by the deal.II authors +## +## This file is part of the deal.II library. +## +## The deal.II library is free software; you can use it, redistribute +## 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. +## The full text of the license can be found in the file LICENSE at +## the top level of the deal.II distribution. +## +## --------------------------------------------------------------------- + +# +# A small macro to reset the CMAKE_REQUIRED_* variables to its default +# values +# +# Usage: +# RESET_CMAKE_REQUIRED_FLAGS +# + +MACRO(RESET_CMAKE_REQUIRED) + SET(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS_SAVED}) + SET(CMAKE_REQUIRED_INCLUDES) + SET(CMAKE_REQUIRED_LIBRARIES) +ENDMACRO() + diff --git a/deal.II/cmake/modules/FindARPACK.cmake b/deal.II/cmake/modules/FindARPACK.cmake index 243899b9e0..f2bb51d628 100644 --- a/deal.II/cmake/modules/FindARPACK.cmake +++ b/deal.II/cmake/modules/FindARPACK.cmake @@ -34,7 +34,7 @@ SET_IF_EMPTY(ARPACK_DIR "$ENV{ARPACK_DIR}") # # ARPACK needs LAPACK and BLAS as dependencies: # -FIND_PACKAGE(LAPACK) +FIND_PACKAGE(DEALII_LAPACK) FIND_LIBRARY(ARPACK_LIBRARY NAMES arpack diff --git a/deal.II/cmake/modules/FindDEALII_LAPACK.cmake b/deal.II/cmake/modules/FindDEALII_LAPACK.cmake new file mode 100644 index 0000000000..b1c7630265 --- /dev/null +++ b/deal.II/cmake/modules/FindDEALII_LAPACK.cmake @@ -0,0 +1,138 @@ +## --------------------------------------------------------------------- +## $Id$ +## +## Copyright (C) 2013 by the deal.II authors +## +## This file is part of the deal.II library. +## +## The deal.II library is free software; you can use it, redistribute +## 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. +## The full text of the license can be found in the file LICENSE at +## the top level of the deal.II distribution. +## +## --------------------------------------------------------------------- + +# +# This module is a wrapper around the FindLAPACK.cmake module provided by +# CMake. +# +# This module exports +# +# LAPACK_FOUND +# LAPACK_LIBRARIES +# LAPACK_LINKER_FLAGS +# BLAS_FOUND +# BLAS_LIBRARIES +# BLAS_LINKER_FLAGS +# METIS_INCLUDE_DIRS +# + + + +# +# We have to use a trick with CMAKE_PREFIX_PATH to make LAPACK_DIR and +# BLAS_DIR work... +# +SET_IF_EMPTY(BLAS_DIR "$ENV{BLAS_DIR}") +SET_IF_EMPTY(LAPACK_DIR "$ENV{LAPACK_DIR}") + +SET(_cmake_prefix_path_backup "${CMAKE_PREFIX_PATH}") + +SET(CMAKE_PREFIX_PATH ${BLAS_DIR} ${LAPACK_DIR} ${_cmake_prefix_path_backup}) + +FIND_PACKAGE(BLAS) + +SET(CMAKE_PREFIX_PATH ${LAPACK_DIR} ${_cmake_prefix_path_backup}) + +FIND_PACKAGE(LAPACK) + +SET(CMAKE_PREFIX_PATH ${_cmake_prefix_path_backup}) + +MARK_AS_ADVANCED( + atlas_LIBRARY + blas_LIBRARY + gslcblas_LIBRARY + lapack_LIBRARY + m_LIBRARY + ptf77blas_LIBRARY + ptlapack_LIBRARY + refblas_LIBRARY + reflapack_LIBRARY + ) + + +IF(LAPACK_FOUND) + SET(DEALII_LAPACK_FOUND TRUE) + + # + # So, well... LAPACK_LINKER_FLAGS and LAPACK_LIBRARIES should contain the + # complete link interface. But for invalid user overrides we include + # BLAS_LIBRARIES and BLAS_LINKER_FLAGS as well.. + # + IF(NOT LAPACK_LINKER_FLAGS MATCHES "${BLAS_LINKER_FLAGS}") + MESSAGE(STATUS + "Manually adding BLAS_LINKER_FLAGS to LAPACK_LINKER_FLAGS" + ) + ADD_FLAGS(LAPACK_LINKER_FLAGS "${BLAS_LINKER_FLAGS}") + ENDIF() + IF(NOT "${LAPACK_LIBRARIES}" MATCHES "${BLAS_LIBRARIES}") + MESSAGE(STATUS + "Manually adding BLAS_LIBRARIES to LAPACK_LIBRARIES" + ) + LIST(APPEND LAPACK_LIBRARIES ${BLAS_LIBRARIES}) + ENDIF() + + # + # Well, in case of static archives we have to manually pick up the + # complete link interface. *sigh* + # + # Do this unconditionally for the most common case: + # TODO: Non-GNU setups... + # + # Switch the library preference back to prefer dynamic libraries if + # DEAL_II_PREFER_STATIC_LIBS=TRUE but DEAL_II_STATIC_EXECUTABLE=FALSE. In + # this case system libraries should be linked dynamically. + # + SWITCH_LIBRARY_PREFERENCE() + FOREACH(_lib gfortran m quadmath) + FIND_LIBRARY(${_lib}_LIBRARY + NAMES ${_lib} + HINTS ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) + MARK_AS_ADVANCED(${_lib}_LIBRARY) + + IF(NOT ${_lib}_LIBRARY MATCHES "-NOTFOUND") + LIST(APPEND BLAS_LIBRARIES ${${_lib}_LIBRARY}) + LIST(APPEND LAPACK_LIBRARIES ${${_lib}_LIBRARY}) + ENDIF() + ENDFOREACH() + SWITCH_LIBRARY_PREFERENCE() + + MARK_AS_ADVANCED( + BLAS_DIR + LAPACK_DIR + ) + +ELSE() + SET(DEALII_LAPACK_FOUND FALSE) + + SET(LAPACK_DIR "" CACHE PATH + "An optional hint to a LAPACK installation" + ) + SET(BLAS_DIR "" CACHE PATH + "An optional hint to a BLAS installation" + ) + + # + # If we couldn't find LAPACK, clean up the library variables: + # + + IF("${BLAS_LIBRARIES}" STREQUAL "FALSE") + SET(BLAS_LIBRARIES "") + ENDIF() + IF("${LAPACK_LIBRARIES}" STREQUAL "FALSE") + SET(LAPACK_LIBRARIES "") + ENDIF() + +ENDIF() diff --git a/deal.II/cmake/modules/FindMETIS.cmake b/deal.II/cmake/modules/FindMETIS.cmake index f0cfa9eba7..80cbd97d47 100644 --- a/deal.II/cmake/modules/FindMETIS.cmake +++ b/deal.II/cmake/modules/FindMETIS.cmake @@ -21,6 +21,9 @@ # # METIS_LIBRARIES # METIS_INCLUDE_DIRS +# METIS_VERSION +# METIS_VERSION_MAJOR +# METIS_VERSION_MINOR # INCLUDE(FindPackageHandleStandardArgs) @@ -87,13 +90,27 @@ IF(METIS_FOUND) # # Extract the version number out of metis.h # - FILE(STRINGS "${METIS_INCLUDE_DIR}/metis.h" METIS_MAJOR_STRING - REGEX "METIS_VER_MAJOR") - STRING(REGEX REPLACE "^.*METIS_VER_MAJOR.* ([0-9]+).*" "\\1" METIS_MAJOR "${METIS_MAJOR_STRING}") - - FILE(STRINGS "${METIS_INCLUDE_DIR}/metis.h" METIS_MINOR_STRING - REGEX "METIS_VER_MINOR") - STRING(REGEX REPLACE "^.*METIS_VER_MINOR.* ([0-9]+).*" "\\1" METIS_MINOR "${METIS_MINOR_STRING}") + FILE(STRINGS "${METIS_INCLUDE_DIR}/metis.h" _metis_major_string + REGEX "METIS_VER_MAJOR" + ) + STRING(REGEX REPLACE "^.*METIS_VER_MAJOR.* ([0-9]+).*" "\\1" + METIS_VERSION_MAJOR "${_metis_major_string}" + ) + FILE(STRINGS "${METIS_INCLUDE_DIR}/metis.h" _metis_minor_string + REGEX "METIS_VER_MINOR" + ) + STRING(REGEX REPLACE "^.*METIS_VER_MINOR.* ([0-9]+).*" "\\1" + METIS_VERSION_MINOR "${_metis_minor_string}" + ) + FILE(STRINGS "${METIS_INCLUDE_DIR}/metis.h" _metis_subminor_string + REGEX "METIS_VER_SUBMINOR" + ) + STRING(REGEX REPLACE "^.*METIS_VER_SUBMINOR.* ([0-9]+).*" "\\1" + METIS_VERSION_SUBMINOR "${_metis_subminor_string}" + ) + SET(METIS_VERSION + "${METIS_VERSION_MAJOR}.${METIS_VERSION_MINOR}.${METIS_VERSION_SUBMINOR}" + ) MARK_AS_ADVANCED(METIS_DIR) ELSE() diff --git a/deal.II/cmake/modules/FindP4EST.cmake b/deal.II/cmake/modules/FindP4EST.cmake index 06e031198a..173da3893a 100644 --- a/deal.II/cmake/modules/FindP4EST.cmake +++ b/deal.II/cmake/modules/FindP4EST.cmake @@ -21,6 +21,11 @@ # P4EST_LIBRARIES # P4EST_INCLUDE_DIRS # P4EST_WITH_MPI +# P4EST_VERSION +# P4EST_VERSION_MAJOR +# P4EST_VERSION_MINOR +# P4EST_VERSION_SUBMINOR +# P4EST_VERSION_PATCH # INCLUDE(FindPackageHandleStandardArgs) @@ -50,7 +55,7 @@ ENDIF() # given, take what we chose for p4est. # -FIND_PATH(P4EST_INCLUDE_DIR p4est.h +FIND_PATH(P4EST_INCLUDE_DIR p4est_config.h HINTS ${P4EST_DIR} PATH_SUFFIXES @@ -121,6 +126,27 @@ IF(P4EST_FOUND) SET(P4EST_WITH_MPI TRUE) ENDIF() + # + # Extract version numbers: + # + FILE(STRINGS "${P4EST_INCLUDE_DIR}/p4est_config.h" P4EST_VERSION + REGEX "#define P4EST_VERSION \"") + STRING(REGEX REPLACE "^.*P4EST_VERSION.*\"([0-9]+.*)\".*" "\\1" + P4EST_VERSION "${P4EST_VERSION}" + ) + STRING(REGEX REPLACE + "^([0-9]+).*$" "\\1" + P4EST_VERSION_MAJOR "${P4EST_VERSION}") + STRING(REGEX REPLACE + "^[0-9]+\\.([0-9]+).*$" "\\1" + P4EST_VERSION_MINOR "${P4EST_VERSION}") + STRING(REGEX REPLACE + "^[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" + P4EST_VERSION_SUBMINOR "${P4EST_VERSION}") + STRING(REGEX REPLACE + "^[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" + P4EST_VERSION_PATCH "${P4EST_VERSION}") + MARK_AS_ADVANCED(P4EST_DIR) ELSE() SET(P4EST_DIR "" CACHE PATH diff --git a/deal.II/cmake/modules/FindPETSC.cmake b/deal.II/cmake/modules/FindPETSC.cmake index 119fa42026..1b2bce5049 100644 --- a/deal.II/cmake/modules/FindPETSC.cmake +++ b/deal.II/cmake/modules/FindPETSC.cmake @@ -199,7 +199,9 @@ IF(PETSC_FOUND) PETSC_VERSION_PATCH "${PETSC_VERSION_PATCH_STRING}" ) - SET(PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}") + SET(PETSC_VERSION + "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.${PETSC_VERSION_PATCH}" + ) MARK_AS_ADVANCED(PETSC_ARCH PETSC_DIR) ELSE() diff --git a/deal.II/cmake/modules/FindSCALAPACK.cmake b/deal.II/cmake/modules/FindSCALAPACK.cmake index 4cd616dbae..96a6a539b3 100644 --- a/deal.II/cmake/modules/FindSCALAPACK.cmake +++ b/deal.II/cmake/modules/FindSCALAPACK.cmake @@ -41,7 +41,7 @@ FIND_LIBRARY(SCALAPACK_LIBRARY NAMES scalapack # SCALAPACK needs LAPACK and BLAS as dependency, search for them with the help # of the LAPACK find module: # -FIND_PACKAGE(LAPACK) +FIND_PACKAGE(DEALII_LAPACK) # # Well, depending on the version of scalapack and the distribution it might diff --git a/deal.II/cmake/modules/FindSLEPC.cmake b/deal.II/cmake/modules/FindSLEPC.cmake index ddb706d05b..9de3500f45 100644 --- a/deal.II/cmake/modules/FindSLEPC.cmake +++ b/deal.II/cmake/modules/FindSLEPC.cmake @@ -121,7 +121,9 @@ IF(SLEPC_FOUND) SLEPC_VERSION_PATCH "${SLEPC_VERSION_PATCH_STRING}" ) - SET(SLEPC_VERSION "${SLEPC_VERSION_MAJOR}.${SLEPC_VERSION_MINOR}.${SLEPC_VERSION_SUBMINOR}") + SET(SLEPC_VERSION + "${SLEPC_VERSION_MAJOR}.${SLEPC_VERSION_MINOR}.${SLEPC_VERSION_SUBMINOR}.${SLEPC_VERSION_PATCH}" + ) MARK_AS_ADVANCED(SLEPC_DIR) ELSE() diff --git a/deal.II/cmake/modules/FindTRILINOS.cmake b/deal.II/cmake/modules/FindTRILINOS.cmake index f5f8d2240d..b347b32ccf 100644 --- a/deal.II/cmake/modules/FindTRILINOS.cmake +++ b/deal.II/cmake/modules/FindTRILINOS.cmake @@ -19,13 +19,16 @@ # # This module exports: # -# TRILINOS_DIR (cached) +# TRILINOS_DIR # TRILINOS_INCLUDE_DIRS # TRILINOS_LIBRARIES +# TRILINOS_VERSION # TRILINOS_VERSION_MAJOR # TRILINOS_VERSION_MINOR # TRILINOS_VERSION_SUBMINOR # TRILINOS_WITH_MPI +# TRILINOS_SUPPORTS_CPP11 +# TRILINOS_HAS_C99_TR1_WORKAROUND # INCLUDE(FindPackageHandleStandardArgs) @@ -33,13 +36,13 @@ INCLUDE(FindPackageHandleStandardArgs) SET_IF_EMPTY(TRILINOS_DIR "$ENV{TRILINOS_DIR}") # -# Include the trilinos package configuration: +# Do not include TrilinosConfig.cmake directly, it is just too big o_O # -FIND_PACKAGE(TRILINOS_CONFIG - CONFIG QUIET - NAMES Trilinos TRILINOS +# Just search for the file: +# +FIND_FILE(TRILINOS_CONFIG + NAMES TrilinosConfig.cmake trilinos-config.cmake HINTS - ${TRILINOS_DIR}/lib/cmake/Trilinos ${TRILINOS_DIR} PATH_SUFFIXES lib64/cmake/Trilinos @@ -50,7 +53,72 @@ FIND_PACKAGE(TRILINOS_CONFIG NO_SYSTEM_ENVIRONMENT_PATH ) -SET(TRILINOS_INCLUDE_DIRS ${Trilinos_INCLUDE_DIRS}) +IF(NOT "${TRILINOS_CONFIG}" STREQUAL "${TRILINOS_CONFIG_SAVED}") + SET(_new_trilinos_config TRUE) +ENDIF() +SET(TRILINOS_CONFIG_SAVED "${TRILINOS_CONFIG}" CACHE INTERNAL "" FORCE) + + +IF(NOT TRILINOS_CONFIG MATCHES "-NOTFOUND") + + SET(_filtered_trilinos_config + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TrilinosConfig.cmake" + ) + + IF(_new_trilinos_config) + GET_FILENAME_COMPONENT(_trilinos_path "${TRILINOS_CONFIG}" PATH) + FILE(WRITE ${_filtered_trilinos_config} "SET(_cmake_current_list_dir ${_trilinos_path})\n") + + # + # Only pick up every line that starts with "^SET("... + # + FILE(STRINGS "${TRILINOS_CONFIG}" _trilinos_config_filtered REGEX "^SET") + + FOREACH(_line ${_trilinos_config_filtered}) + STRING(REPLACE "CMAKE_CURRENT_LIST_DIR" "_cmake_current_list_dir" + _line "${_line}" + ) + FILE(APPEND ${_filtered_trilinos_config} "${_line}\n") + ENDFOREACH() + ENDIF() + + # + # ... and include only that: + # + INCLUDE(${_filtered_trilinos_config}) + + SET(TRILINOS_CONFIG_FOUND TRUE) +ENDIF() + + +# +# Look for the one include file that we'll query for further information: +# +IF(_new_trilinos_config) + UNSET(EPETRA_CONFIG_H CACHE) +ENDIF() +FIND_FILE(EPETRA_CONFIG_H Epetra_config.h + HINTS ${Trilinos_INCLUDE_DIRS} + NO_DEFAULT_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_CMAKE_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH + NO_CMAKE_FIND_ROOT_PATH + ) +IF(EPETRA_CONFIG_H MATCHES "-NOTFOUND") + SET(TRILINOS_CONFIG_FOUND FALSE) +ELSE() + SET(TRILINOS_INCLUDE_DIRS ${Trilinos_INCLUDE_DIRS}) + # + # *Boy* Sanitize the include paths given by TrilinosConfig.cmake... + # + STRING(REGEX REPLACE + "(lib64|lib)\\/cmake\\/Trilinos\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/" "" + TRILINOS_INCLUDE_DIRS "${TRILINOS_INCLUDE_DIRS}" + ) +ENDIF() + # # We'd like to have the full library names but the Trilinos package only @@ -58,6 +126,10 @@ SET(TRILINOS_INCLUDE_DIRS ${Trilinos_INCLUDE_DIRS}) # So we check again for every lib and store the full path: # FOREACH(_library ${Trilinos_LIBRARIES}) + IF(_new_trilinos_config) + UNSET(TRILINOS_LIBRARY_${_library} CACHE) + ENDIF() + FIND_LIBRARY(TRILINOS_LIBRARY_${_library} NAMES ${_library} HINTS ${Trilinos_LIBRARY_DIRS} @@ -69,13 +141,11 @@ FOREACH(_library ${Trilinos_LIBRARIES}) NO_CMAKE_FIND_ROOT_PATH ) - LIST(APPEND TRILINOS_LIBRARIES ${TRILINOS_LIBRARY_${_library}}) - - # - # Remove the variables from the cache, so that updating TRILINOS_DIR will - # find the new libraries.. - # - UNSET(TRILINOS_LIBRARY_${_library} CACHE) + IF(TRILINOS_LIBRARY_${_library} MATCHES "-NOTFOUND") + SET(TRILINOS_CONFIG_FOUND FALSE) + ELSE() + LIST(APPEND TRILINOS_LIBRARIES ${TRILINOS_LIBRARY_${_library}}) + ENDIF() ENDFOREACH() # @@ -96,8 +166,10 @@ MARK_AS_ADVANCED(TRILINOS_CONFIG_DIR) IF(TRILINOS_FOUND) # - # Extract the major and minor version numbers: + # Extract version numbers: # + SET(TRILINOS_VERSION "${Trilinos_VERSION}") + STRING(REGEX REPLACE "^([0-9]+).*$" "\\1" TRILINOS_VERSION_MAJOR "${Trilinos_VERSION}") @@ -113,15 +185,6 @@ IF(TRILINOS_FOUND) # # Determine whether Trilinos was configured with MPI and 64bit indices: # - FIND_FILE(EPETRA_CONFIG_H Epetra_config.h - HINTS ${TRILINOS_INCLUDE_DIRS} - NO_DEFAULT_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_CMAKE_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH - NO_CMAKE_FIND_ROOT_PATH - ) FILE(STRINGS "${EPETRA_CONFIG_H}" EPETRA_MPI_STRING REGEX "#define HAVE_MPI") IF("${EPETRA_MPI_STRING}" STREQUAL "") @@ -144,10 +207,46 @@ IF(TRILINOS_FOUND) SET(TRILINOS_WITH_NO_64BITS_INDICES FALSE) ENDIF() - UNSET(EPETRA_CONFIG_H CACHE) + # + # Some versions of Sacado_cmath.hpp do things that aren't compatible + # with the -std=c++0x flag of GCC, see deal.II FAQ. + # Test whether that is indeed the case: + # + IF(_new_trilinos_config) + UNSET(TRILINOS_SUPPORTS_CPP11 CACHE) + UNSET(TRILINOS_HAS_C99_TR1_WORKAROUND CACHE) + ENDIF() + + LIST(APPEND CMAKE_REQUIRED_INCLUDES ${TRILINOS_INCLUDE_DIRS}) + PUSH_TEST_FLAG("${DEAL_II_CXX11_FLAG}") + + CHECK_CXX_SOURCE_COMPILES( + " + #include + int main(){ return 0; } + " + TRILINOS_SUPPORTS_CPP11 + ) + + # + # Try whether exporting HAS_C99_TR1_CMATH helps: + # + PUSH_TEST_FLAG("-DHAS_C99_TR1_CMATH") + CHECK_CXX_SOURCE_COMPILES( + " + #include + int main(){ return 0; } + " + TRILINOS_HAS_C99_TR1_WORKAROUND + ) + + RESET_CMAKE_REQUIRED() + MARK_AS_ADVANCED(TRILINOS_DIR) + ELSE() + SET(TRILINOS_DIR "" CACHE PATH "An optional hint to a Trilinos installation" ) diff --git a/deal.II/cmake/modules/FindUMFPACK.cmake b/deal.II/cmake/modules/FindUMFPACK.cmake index 378b68cb56..746fdf0143 100644 --- a/deal.II/cmake/modules/FindUMFPACK.cmake +++ b/deal.II/cmake/modules/FindUMFPACK.cmake @@ -36,7 +36,7 @@ ENDFOREACH() # TODO: There might be an external dependency for metis, ignore this for # now. # -FIND_PACKAGE(LAPACK) +FIND_PACKAGE(DEALII_LAPACK) FIND_PACKAGE(METIS) # diff --git a/deal.II/cmake/setup_cached_variables.cmake b/deal.II/cmake/setup_cached_variables.cmake index e8667e17c1..c2e04fe20d 100644 --- a/deal.II/cmake/setup_cached_variables.cmake +++ b/deal.II/cmake/setup_cached_variables.cmake @@ -39,7 +39,6 @@ # DEAL_II_PREFER_STATIC_LIBS # DEAL_II_STATIC_EXECUTABLE # CMAKE_INSTALL_RPATH_USE_LINK_PATH -# CMAKE_C_FLAGS *) # CMAKE_CXX_FLAGS *) # DEAL_II_LINKER_FLAGS *) # DEAL_II_CXX_FLAGS_DEBUG @@ -48,7 +47,7 @@ # DEAL_II_LINKER_FLAGS_RELEASE # DEAL_II_WITH_64BIT_INDICES # -# *) May also be set via environment variable (CFLAGS, CXXFLAGS, LDFLAGS) +# *) May also be set via environment variable (CXXFLAGS, LDFLAGS) # (a nonempty cached variable has precedence and will not be # overwritten by environment) # @@ -142,7 +141,7 @@ ENDIF() OPTION(DEAL_II_ALLOW_PLATFORM_INTROSPECTION - "Allow platform introspection for CPU command set, SSE and AVX" + "Allow platform introspection for CPU command sets, SSE and AVX" ON ) MARK_AS_ADVANCED(DEAL_II_ALLOW_PLATFORM_INTROSPECTION) @@ -201,7 +200,6 @@ OPTION(DEAL_II_WITH_64BIT_INDICES ) - # # Tell the user very prominently, that we're doing things differently w.r.t # CMAKE_(C|CXX)_FLAGS_(DEBUG|RELEASE) @@ -213,6 +211,7 @@ FOREACH(_flag SHARED_LINKER_FLAGS_DEBUG ) IF(NOT "${CMAKE_${_flag}}" STREQUAL "") + UNSET(${CMAKE_${_flag}} CACHE) MESSAGE(FATAL_ERROR "\nThe deal.II cmake build system does not use CMAKE_${_flag}.\n" "Use DEAL_II_${_flag}, instead!\n\n" @@ -220,6 +219,7 @@ FOREACH(_flag ENDIF() ENDFOREACH() + # # Hide all unused compiler flag variables: # @@ -246,6 +246,7 @@ FOREACH(_flag SET(${_flag} "" CACHE INTERNAL "" FORCE) ENDFOREACH() + # # Set cached compiler flags to an empty string: # diff --git a/deal.II/cmake/setup_compiler_flags.cmake b/deal.II/cmake/setup_compiler_flags.cmake index 4815abf65f..f82147f9e8 100644 --- a/deal.II/cmake/setup_compiler_flags.cmake +++ b/deal.II/cmake/setup_compiler_flags.cmake @@ -65,22 +65,25 @@ # # Check the user provided CXX flags: # + MESSAGE(STATUS "") IF(NOT "${CMAKE_CXX_FLAGS_SAVED}" STREQUAL "${DEAL_II_CXX_FLAGS_SAVED}") + # Rerun this test if cxx flags changed: UNSET(DEAL_II_HAVE_USABLE_CXX_FLAGS CACHE) ENDIF() SET(DEAL_II_CXX_FLAGS_SAVED "${CMAKE_CXX_FLAGS_SAVED}" CACHE INTERNAL "" FORCE) -SET(CMAKE_REQUIRED_FLAGS "${CMAKE_CXX_FLAGS_SAVED}") +# Initialize all CMAKE_REQUIRED_* variables a this point: +RESET_CMAKE_REQUIRED() + CHECK_CXX_SOURCE_COMPILES( "int main(){ return 0; }" DEAL_II_HAVE_USABLE_CXX_FLAGS) -SET(CMAKE_REQUIRED_FLAGS "") IF(NOT DEAL_II_HAVE_USABLE_CXX_FLAGS) UNSET(DEAL_II_HAVE_USABLE_CXX_FLAGS CACHE) MESSAGE(FATAL_ERROR "\n" - "Configuration error: Cannot compile with the specified CXX flags: " + "Configuration error: Cannot compile with the user supplied CXX flags:\n" "${CMAKE_CXX_FLAGS_SAVED}\n" ) ENDIF() diff --git a/deal.II/cmake/setup_compiler_flags_gnu.cmake b/deal.II/cmake/setup_compiler_flags_gnu.cmake index 63bf98e31a..14884e265d 100644 --- a/deal.II/cmake/setup_compiler_flags_gnu.cmake +++ b/deal.II/cmake/setup_compiler_flags_gnu.cmake @@ -73,6 +73,12 @@ ENABLE_IF_SUPPORTED(CMAKE_CXX_FLAGS "-Wswitch") # ENABLE_IF_SUPPORTED(CMAKE_CXX_FLAGS "-Wno-unused-local-typedefs") +# +# Disable Wlong-long that will trigger a lot of warnings when compiling +# with disabled C++11 support: +# +ENABLE_IF_SUPPORTED(CMAKE_CXX_FLAGS "-Wno-long-long") + # # Disable deprecation warnings # @@ -148,7 +154,7 @@ IF (CMAKE_BUILD_TYPE MATCHES "Debug") # # If -Og is not available, fall back to -O0: # - IF(NOT DEAL_II_HAVE_FLAG_O0) + IF(NOT DEAL_II_HAVE_FLAG_Og) ADD_FLAGS(DEAL_II_CXX_FLAGS_DEBUG "-O0") ENDIF() diff --git a/deal.II/cmake/setup_compiler_flags_intel.cmake b/deal.II/cmake/setup_compiler_flags_intel.cmake index e08b7a382a..ed67d96ad3 100644 --- a/deal.II/cmake/setup_compiler_flags_intel.cmake +++ b/deal.II/cmake/setup_compiler_flags_intel.cmake @@ -104,11 +104,24 @@ IF (CMAKE_BUILD_TYPE MATCHES "Release") # # General optimization flags: # - ADD_FLAGS(DEAL_II_CXX_FLAGS_RELEASE "-O1") + + IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "13.0" ) + ADD_FLAGS(DEAL_II_CXX_FLAGS_RELEASE "-O2") + ELSE() + # + # Disable aggressive optimization for intel-13* compilers, until we + # resolve a lot of funny miscompilations... + # + # - Maier, 2013 + # + ADD_FLAGS(DEAL_II_CXX_FLAGS_RELEASE "-O1") + ENDIF() + ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS_RELEASE "-ip") ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS_RELEASE "-funroll-loops") - ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS_RELEASE "-ansi-alias") # equiv. -fstrict-aliasing + # equivalent to -fno-strict-aliasing: + ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS_RELEASE "-no-ansi-alias") ENDIF() diff --git a/deal.II/cmake/setup_deal_ii.cmake b/deal.II/cmake/setup_deal_ii.cmake index 931bf618f3..a07c54f465 100644 --- a/deal.II/cmake/setup_deal_ii.cmake +++ b/deal.II/cmake/setup_deal_ii.cmake @@ -51,8 +51,6 @@ # DEAL_II_PROJECT_CONFIG_RELDIR *) # # DEAL_II_BUILD_TYPES -# DEAL_II_WITH_BUNDLED_DIRECTORY -# DEAL_II_WITH_DOC_DIRECTORY # # *) Can be overwritten by the command line via -D<...> # @@ -112,7 +110,7 @@ IF(DEAL_II_COMPONENT_COMPAT_FILES) (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") ) # # Ensure that in case of an out of source build BINARY_DIR/include != - # INSTALL_PREFIX/include us always true. Otherwise stale headers might + # INSTALL_PREFIX/include is always true. Otherwise stale headers might # get included resulting in a failing build. # SET_IF_EMPTY(DEAL_II_INCLUDE_RELDIR "include/install") @@ -146,49 +144,3 @@ IF(CMAKE_BUILD_TYPE MATCHES "Release") LIST(APPEND DEAL_II_BUILD_TYPES "RELEASE") ENDIF() - -######################################################################## -# # -# Cleanup and setup that has to happen after the call to PROJECT(): # -# # -######################################################################## - -# -# Cleanup some files used for storing the names of all object targets that -# will be bundled to the deal.II library. -# (Right now, i.e. cmake 2.8.8, this is the only reliable way to get -# information into a global scope...) -# -FOREACH(_build ${DEAL_II_BUILD_TYPES}) - STRING(TOLOWER "${_build}" _build_lowercase) - FILE(REMOVE - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/deal_ii_objects_${_build_lowercase} - ) -ENDFOREACH() - -IF(DEAL_II_PREFER_STATIC_LIBS) - # - # Invert the search order for libraries when DEAL_II_PREFER_STATIC_LIBS - # is set. This will prefer static archives instead of shared libraries: - # - # TODO: Does this work on a Windows or CYGWIN target? - LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES) -ENDIF() - -# -# Cross compilation stuff: -# -IF(CMAKE_CROSSCOMPILING) - # - # Disable platform introspection when cross compiling - # - SET(DEAL_II_ALLOW_PLATFORM_INTROSPECTION OFF CACHE BOOL "" FORCE) - - # - # Import native expand_instantiations for use in cross compilation: - # - SET(DEAL_II_NATIVE "DEAL_II_NATIVE-NOTFOUND" CACHE FILEPATH - "A pointer to a native deal.Ii build directory" - ) - INCLUDE(${DEAL_II_NATIVE}/cmake/scripts/importExecutables.cmake) -ENDIF() diff --git a/deal.II/cmake/setup_finalize.cmake b/deal.II/cmake/setup_finalize.cmake index e2f919a309..a651931f34 100644 --- a/deal.II/cmake/setup_finalize.cmake +++ b/deal.II/cmake/setup_finalize.cmake @@ -60,6 +60,19 @@ FOREACH(_build ${DEAL_II_BUILD_TYPES}) ENDIF() ENDFOREACH() +# +# Cleanup some files used for storing the names of all object targets that +# will be bundled to the deal.II library. +# (Right now, i.e. cmake 2.8.8, this is the only reliable way to get +# information into a global scope...) +# +FOREACH(_build ${DEAL_II_BUILD_TYPES}) + STRING(TOLOWER "${_build}" _build_lowercase) + FILE(REMOVE + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/deal_ii_objects_${_build_lowercase} + ) +ENDFOREACH() + ######################################################################## # # @@ -159,9 +172,7 @@ FOREACH(_var ${_variables}) LIST(APPEND _components "${_var}") ELSEIF(_var MATCHES "(MPI_CXX_COMPILER|MPI_CXX_COMPILE_FLAGS|MPI_CXX_LINK_FLAGS)") LIST(APPEND _features_config ${_var}) - ELSEIF(_var MATCHES "(LIBRARIES|INCLUDE_PATH|INCLUDE_DIRS|LINKER_FLAGS)" - # Avoid a lot of Trilinos variables: - AND (NOT _var MATCHES "_TPL_|_MPI_") ) + ELSEIF(_var MATCHES "(LIBRARIES|INCLUDE_PATH|INCLUDE_DIRS|LINKER_FLAGS)") LIST(APPEND _features_config ${_var}) ENDIF() ENDFOREACH() @@ -173,6 +184,20 @@ FOREACH(_var ${_features}) IF(FEATURE_${_feature}_EXTERNAL_CONFIGURED) _both("# ${_var} set up with external dependencies\n") + # + # Print out version number: + # + IF(DEFINED ${_feature}_VERSION) + _detailed("# ${_feature}_VERSION = ${${_feature}_VERSION}\n") + ENDIF() + + # + # Print out ${_feature}_DIR: + # + IF(DEFINED ${_feature}_DIR) + _detailed("# ${_feature}_DIR = ${${_feature}_DIR}\n") + ENDIF() + # # Print the feature configuration: # diff --git a/deal.II/cmake/setup_post_project_call.cmake b/deal.II/cmake/setup_post_project_call.cmake new file mode 100644 index 0000000000..690acf5d5d --- /dev/null +++ b/deal.II/cmake/setup_post_project_call.cmake @@ -0,0 +1,53 @@ +## --------------------------------------------------------------------- +## $Id$ +## +## Copyright (C) 2013 by the deal.II authors +## +## This file is part of the deal.II library. +## +## The deal.II library is free software; you can use it, redistribute +## 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. +## The full text of the license can be found in the file LICENSE at +## the top level of the deal.II distribution. +## +## --------------------------------------------------------------------- + + +######################################################################## +# # +# Setup that has to happen after the call to PROJECT(): # +# # +######################################################################## + +# +# Library search order: +# +IF(DEAL_II_PREFER_STATIC_LIBS) + # + # Invert the search order for libraries when DEAL_II_PREFER_STATIC_LIBS + # is set. This will prefer static archives instead of shared libraries: + # + # TODO: Does this work on a Windows or CYGWIN target? + LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES) +ENDIF() + + +# +# Cross compilation stuff: +# +IF(CMAKE_CROSSCOMPILING) + # + # Disable platform introspection when cross compiling + # + SET(DEAL_II_ALLOW_PLATFORM_INTROSPECTION OFF CACHE BOOL "" FORCE) + + # + # Import native expand_instantiations for use in cross compilation: + # + SET(DEAL_II_NATIVE "DEAL_II_NATIVE-NOTFOUND" CACHE FILEPATH + "A pointer to a native deal.Ii build directory" + ) + INCLUDE(${DEAL_II_NATIVE}/cmake/scripts/importExecutables.cmake) +ENDIF() diff --git a/deal.II/contrib/mesh_conversion/README.txt b/deal.II/contrib/mesh_conversion/README.txt index 77f4d27d0f..ef00b074b1 100644 --- a/deal.II/contrib/mesh_conversion/README.txt +++ b/deal.II/contrib/mesh_conversion/README.txt @@ -6,7 +6,7 @@ Use: Convert an ABAQUS .inp file to an AVS UCD file. Author: Jean-Paul Pelteret jppelteret.uct@gmail.com - modified by: Timo Heister, heister@math.tamu.edu + modified by: Timo Heister, heister@clemson.edu =================================================== diff --git a/deal.II/doc/CMakeLists.txt b/deal.II/doc/CMakeLists.txt index eeb7064928..8e63586481 100644 --- a/deal.II/doc/CMakeLists.txt +++ b/deal.II/doc/CMakeLists.txt @@ -15,11 +15,6 @@ ## --------------------------------------------------------------------- -# -# Required packages for the document generation: -# -FIND_PACKAGE(Perl) -FIND_PACKAGE(Doxygen) # @@ -27,6 +22,12 @@ FIND_PACKAGE(Doxygen) # IF(DEAL_II_COMPONENT_DOCUMENTATION) + # + # Required packages for the document generation: + # + FIND_PACKAGE(Perl) + FIND_PACKAGE(Doxygen) + # # Do we have all necessary dependencies? # diff --git a/deal.II/doc/authors.html b/deal.II/doc/authors.html index 1af8db86d0..494df11f73 100644 --- a/deal.II/doc/authors.html +++ b/deal.II/doc/authors.html @@ -30,9 +30,9 @@
  • - Timo Heister, - Texas A&M University, TX, USA + Clemson University, SC, USA
  • @@ -164,6 +164,9 @@ Support for arbitrary nodes in FE_Q. Matrix-free framework. step-37 and step-48 tutorial programs. +
  • Oleh Krehel: + Many documentation fixes. +
  • Martin Kronbichler: step-22, step-31, step-32, step-37, step-48, interfaces to Trilinos, significant parts of ConstraintMatrix, matrix-free diff --git a/deal.II/doc/development/Config.sample b/deal.II/doc/development/Config.sample index 6f4ad89247..aeb340ced3 100644 --- a/deal.II/doc/development/Config.sample +++ b/deal.II/doc/development/Config.sample @@ -243,7 +243,15 @@ # BLA_VENDOR will also be recognized by FindLAPACK.cmake. # # If your BLAS/LAPACK installation resides at a non system location, specify -# a hint with CMAKE_PREFIX_PATH. +# a hint with LAPACK_DIR and BLAS_DIR, or CMAKE_PREFIX_PATH: +# +# SET(LAPACK_DIR "..." CACHE PATH +# "The preferred installation prefix for searching for LAPACK" +# ) +# +# SET(BLAS_DIR "..." CACHE PATH +# "The preferred installation prefix for searching for BLAS" +# ) # # # Manual setup: diff --git a/deal.II/doc/development/cmake-internals.html b/deal.II/doc/development/cmake-internals.html index cacc2e4bbe..903af06bfa 100644 --- a/deal.II/doc/development/cmake-internals.html +++ b/deal.II/doc/development/cmake-internals.html @@ -19,7 +19,7 @@

    This page provides details about the CMake build system. Files processed by the top level CMakeLists.txt script are - listed in the TOC in cronological order. + listed in the TOC in chronological order.

    @@ -115,7 +115,7 @@ ) CMake operates almost always with variables in global state. To guard - against accidential overwrite of variables the following naming + against accidental overwrite of variables the following naming conventions must be followed at all times:

    • @@ -260,11 +260,11 @@
       
           CHECK_CXX_SOURCE_COMPILES(source variable)
      -      - Checks whether it is possible to compile _and_ link the code snipet
      -        <source>. If succesful, variable is set to 1.
      +      - Checks whether it is possible to compile _and_ link the code snippet
      +        <source>. If successful, variable is set to 1.
       
           CHECK_CXX_SOURCE_RUNS(source variable)
      -      - variable is set to 1 if <source> coulde be succesfully compiled and
      +      - variable is set to 1 if <source> could be successfully compiled and
               linked and the resulting program ran and exited without error.
               Avoid this macro outside of a DEAL_II_ALLOW_PLATFORM_INTROSPECTION
               guard. A sensible fallback should be provided if the check cannot
      @@ -303,15 +303,18 @@
           POP_TEST_FLAG()
       	  
      -
    • Libraries necessary for linkage can be set in the list variable - CMAKE_REQUIRED_LIBRARIES. It is best two hard set - this variable to a specific value and later on cleaning it, - instead of appending/removing: +
    • Necessary include directories and libraries necessary for + linkage can be set in the list variables + CMAKE_REQUIRED_INCLUDES and + CMAKE_REQUIRED_LIBRARIES. It is best to append these + lists and later on reset CMAKE_REQUIRED_* (including + CMAKE_REQUIRED_FLAGS) to their default values:
       
      -    SET(CMAKE_REQUIRED_LIBRARIES <a list of libraries>
      +    LIST(APPEND CMAKE_REQUIRED_INCLUDES <a list of includes>)
      +    LIST(APPEND CMAKE_REQUIRED_LIBRARIES <a list of libraries>)
           CHECK_CXX_SOURCE_COMPILES(...)
      -    SET(CMAKE_REQUIRED_LIBRARIES)
      +    RESET_CMAKE_REQUIRED()
       	  

    @@ -429,7 +432,7 @@ FEATURE_<FEATURE>_DEPENDS (a variable) - a variable which contains an optional list of other features - this feature depends on (and which have to be enbled for this feature + this feature depends on (and which have to be enabled for this feature to work.) The features must be given with the full option toggle: DEAL_II_WITH_[...] @@ -604,7 +607,7 @@ # Glob for all header files associated with the object target: # As this list is only for cosmetic reasons, so that associated header # files show up in IDEs, we don't manage an explicit list (with the - # tradeoff to have to run "make rebuild_cache" when a new header file + # trade-off to have to run "make rebuild_cache" when a new header file # emerges...) # FILE(GLOB _header @@ -672,7 +675,7 @@
    - The deal.II Group + The deal.II Group $Date$
    diff --git a/deal.II/doc/development/cmake.html b/deal.II/doc/development/cmake.html index 05fe95d6e9..8139fdc110 100644 --- a/deal.II/doc/development/cmake.html +++ b/deal.II/doc/development/cmake.html @@ -123,7 +123,7 @@ switches off support for the METIS library that may have been automatically detected during the first invocation of - cmake and enables support for Trilinos by enablind + cmake and enables support for Trilinos by enabling DEAL_II_WITH_TRILINOS and setting TRILINOS_DIR.

    @@ -380,7 +380,9 @@
     
         ARPACK_DIR,
    +    BOOST_DIR,
         HDF5_DIR,
    +    LAPACK_DIR (and BLAS_DIR),
         METIS_DIR,
         MUMPS_DIR (and SCALAPACK_DIR, BLACS_DIR),
         P4EST_DIR (and SC_DIR),
    @@ -403,7 +405,7 @@
           Alternatively, cached variables set by the
           Find<Module> mechanism may be set,
           hinted or overwritten directly (variable names are highly
    -      dependend on the actual library). You can get a list via
    +      dependent on the actual library). You can get a list via
           
     
         make edit_cache
    @@ -608,7 +610,7 @@
           
    • The compiler must be specified at the very first - invokation of cmake. + invocation of cmake.
    • A working CXX compiler is needed. It is optional to provide a C or Fortran compiler. @@ -796,7 +798,7 @@
      - The deal.II Group + The deal.II Group $Date$
      diff --git a/deal.II/doc/development/cmakelists.html b/deal.II/doc/development/cmakelists.html index 5ebc8bc15f..96f699ef46 100644 --- a/deal.II/doc/development/cmakelists.html +++ b/deal.II/doc/development/cmakelists.html @@ -508,7 +508,7 @@
      - The deal.II Group + The deal.II Group $Date$
      diff --git a/deal.II/doc/development/doxygen.html b/deal.II/doc/development/doxygen.html index 2db340d6a2..ff8d4f55d1 100644 --- a/deal.II/doc/development/doxygen.html +++ b/deal.II/doc/development/doxygen.html @@ -18,7 +18,7 @@

      deal.II has an extensive reference documentation generated by Doxygen. One of the many - features of Doxygen is, that all class names, function noames and so + features of Doxygen is, that all class names, function names and so on are cross-linked in the documentation, and a single click suffices to jump to the documentation of an object.

      diff --git a/deal.II/doc/development/porting.html b/deal.II/doc/development/porting.html index ee4d340d90..07281a2316 100644 --- a/deal.II/doc/development/porting.html +++ b/deal.II/doc/development/porting.html @@ -5,7 +5,7 @@ Porting deal.II - + @@ -23,7 +23,7 @@ Consequently, there is a good chance that deal.II will run on a reasonably well behaved system besides the ones listed - in the ReadMe. Nevertheless, + in the ReadMe. Nevertheless, there are cases where some adjustments are necessary.

      diff --git a/deal.II/doc/doxygen/headers/global_dof_index.h b/deal.II/doc/doxygen/headers/global_dof_index.h index a4b5542416..51ebce36d7 100644 --- a/deal.II/doc/doxygen/headers/global_dof_index.h +++ b/deal.II/doc/doxygen/headers/global_dof_index.h @@ -65,6 +65,7 @@ * can solve now, there is no reason for the number of non-zero entries in a * sparse matrix to go over four billions. Thus, we still use unsigned int * for, e.g., row_lengths in the object. + * * - * + * */ diff --git a/deal.II/doc/doxygen/headers/glossary.h b/deal.II/doc/doxygen/headers/glossary.h index a84c1a6612..a4acb8b8c6 100644 --- a/deal.II/doc/doxygen/headers/glossary.h +++ b/deal.II/doc/doxygen/headers/glossary.h @@ -369,6 +369,11 @@ * faces and edges. In this case, the boundary object associated with a particular * boundary indicator is also used to move the new center points of cells back * onto the manifold that the triangulation describes whenever a cell is refined. + * + * @note For parallel triangulations of type parallel::distributed::Triangulation, + * it is not enough to set boundary indicators only once at the beginning. See + * the long discussion on this topic in the class documentation of + * parallel::distributed::Triangulation . * * * @see @ref boundary "The module on boundaries" @@ -544,7 +549,7 @@ * to adding elements or setting them. In some cases, not all processors may * be adding elements, for example if a processor does not own any cells when * using a very coarse (initial) mesh. For this reason, compress() takes an - * argument of type VectorOperation, which can be either ::add, or ::insert. + * argument of type VectorOperation, which can be either ::%add, or ::%insert. * This argument is required for vectors and matrices starting with the 7.3 * release. * @@ -832,7 +837,10 @@ * is pointing the other direction. There are not very many places in * application programs where you need this information actually, but * a few places in the library make use of this. Note that in 2d, the - * result is always @p true. + * result is always @p true. However, while every face in 2d is always + * in standard orientation, you can sometimes specify something to + * assume that this is not so; an example is the function + * DoFTools::make_periodicity_constraints(). * * There are two other flags that describe the orientation of a face: * face_flip and face_rotation. Some documentation for these @@ -1210,7 +1218,7 @@ Article{JK10, * // in 3d * for (cell=dof_handler.begin_active(); * cell!=dof_handler.end(); ++cell) - * for (unsigned int line=0; line::lines_per_cell; ++l) + * for (unsigned int l=0; l::lines_per_cell; ++l) * if (cell->line(l)->at_boundary()) * { * do something with this line @@ -1266,7 +1274,7 @@ Article{JK10, * @code * for (cell=dof_handler.begin_active(); * cell!=dof_handler.end(); ++cell) - * for (unsigned int line=0; line::lines_per_cell; ++l) + * for (unsigned int l=0; l::lines_per_cell; ++l) * if (cell->line(l)->at_boundary()) * { * cell->line(l)->set_user_index(42); diff --git a/deal.II/doc/doxygen/headers/instantiations.h b/deal.II/doc/doxygen/headers/instantiations.h index 91e95805d0..59c2b3424c 100644 --- a/deal.II/doc/doxygen/headers/instantiations.h +++ b/deal.II/doc/doxygen/headers/instantiations.h @@ -111,7 +111,7 @@ * * @subsection Inst2p Provided instances * - * Like with the classes in section Inst1, the instances provided in the + * Like with the classes in section @ref Inst1, the instances provided in the * library are often listed in the documentation of that class in a form * similar to this: @verbatim diff --git a/deal.II/doc/doxygen/headers/vector_valued.h b/deal.II/doc/doxygen/headers/vector_valued.h index 9c24a2f7c5..2edcd2d5a8 100644 --- a/deal.II/doc/doxygen/headers/vector_valued.h +++ b/deal.II/doc/doxygen/headers/vector_valued.h @@ -684,7 +684,7 @@ \right)_\Omega, @f} * where $\varepsilon(\mathbf u) = \frac 12 \left([\nabla\mathbf u] + - * [\nabla\mathbf u]^2\right)$ is the symmetrized gradient. + * [\nabla\mathbf u]^T\right)$ is the symmetrized gradient. * In the second to last step, we used that the scalar product between * an arbitrary tensor $\nabla\mathbf u$ and a symmetric tensor * $\frac 12[\partial_i v_j + \partial_j v_i]$ equals the scalar product diff --git a/deal.II/doc/doxygen/options.dox.in b/deal.II/doc/doxygen/options.dox.in index e17e334cbf..b57c0c6291 100644 --- a/deal.II/doc/doxygen/options.dox.in +++ b/deal.II/doc/doxygen/options.dox.in @@ -1000,7 +1000,8 @@ PREDEFINED = DOXYGEN=1 \ DEAL_II_WITH_ARPACK=1 \ DEAL_II_WITH_METIS=1 \ DEAL_II_WITH_MUMPS=1 \ - DEAL_II_WITH_P4EST=1 + DEAL_II_WITH_P4EST=1 \ + DEAL_II_WITH_MPI=1 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. diff --git a/deal.II/doc/external-libs/arpack.html b/deal.II/doc/external-libs/arpack.html index ef6593db09..52a6c37202 100644 --- a/deal.II/doc/external-libs/arpack.html +++ b/deal.II/doc/external-libs/arpack.html @@ -6,8 +6,8 @@ The deal.II Readme on interfacing to ARPACK - - + + @@ -103,7 +103,7 @@
      - The deal.II Group + The deal.II Group $Date$
      diff --git a/deal.II/doc/external-libs/mumps.html b/deal.II/doc/external-libs/mumps.html index 6f26ade667..9459e54e4e 100644 --- a/deal.II/doc/external-libs/mumps.html +++ b/deal.II/doc/external-libs/mumps.html @@ -7,7 +7,7 @@ - + @@ -347,7 +347,7 @@
      - The deal.II Group + The deal.II Group $Date$
      diff --git a/deal.II/doc/external-libs/p4est.html b/deal.II/doc/external-libs/p4est.html index 735d088210..67fea34c44 100644 --- a/deal.II/doc/external-libs/p4est.html +++ b/deal.II/doc/external-libs/p4est.html @@ -50,16 +50,19 @@ line like
       
      -    cmake -DP4EST_DIR=/path/to/installation -DDEAL_II_WITH_P4EST=ON -DDEAL_II_WITH_MPI=ON <...>
      +    cmake -DP4EST_DIR=/path/to/installation/FAST -DDEAL_II_WITH_P4EST=ON -DDEAL_II_WITH_MPI=ON <...>
             
      - if the p4est library isn't picked up automatically. Obviously, you + if the p4est library isn't picked up automatically. Note the presence + of /FAST at the end of the path necessary when using + the ./p4est-setup.sh script to select the release + version of p4est. Obviously, you can also add additional flags to cmake as described in the general ReadMe file.


      - The deal.II Group + The deal.II Group $Date$
      diff --git a/deal.II/doc/license.html b/deal.II/doc/license.html index 5470e7573f..0073a3b452 100644 --- a/deal.II/doc/license.html +++ b/deal.II/doc/license.html @@ -136,7 +136,7 @@ Wolfgang Bangerth < bangerth@gmail.com >
    • - Timo Heister < heister@math.tamu.edu > + Timo Heister < heister@clemson.edu >
    • Guido Kanschat < dr.guido.kanschat@gmail.com > @@ -145,6 +145,7 @@

      +

      Full license text

      diff --git a/deal.II/doc/mail.html b/deal.II/doc/mail.html
      index 66574112c1..7e69fbb4bb 100644
      --- a/deal.II/doc/mail.html
      +++ b/deal.II/doc/mail.html
      @@ -77,7 +77,7 @@
               Wolfgang Bangerth < bangerth@gmail.com >
             
    • - Timo Heister < heister@math.tamu.edu > + Timo Heister < heister@clemson.edu >
    • Guido Kanschat < dr.guido.kanschat@gmail.com > diff --git a/deal.II/doc/news/2001/3.1.0-vs-3.2.0.html b/deal.II/doc/news/2001/3.1.0-vs-3.2.0.html index 2bacdd45b2..cd0b779b75 100644 --- a/deal.II/doc/news/2001/3.1.0-vs-3.2.0.html +++ b/deal.II/doc/news/2001/3.1.0-vs-3.2.0.html @@ -144,9 +144,6 @@ documentation, etc. New: There is now some support to include and use routines from the Harwell Subroutine Library. - (See the ReadMe - file for more information on installation of HSL - subroutines.)
      (WB 2001/01/30)

      @@ -156,9 +153,7 @@ documentation, etc. existence of a Fortran 77 compiler, and sets its path, some compiler flags and the libraries to be linked in when mixing C++ and F77 in some variables in the file - common/Make.global_options (see also - this - page). + common/Make.global_options.
      (WB 2000/12/30)

      @@ -602,9 +597,6 @@ documentation, etc. SparseDirectMA27 and SparseDirectMA47 for the sparse direct solvers MA27 and MA47. - (See the ReadMe - file for more information on installation of HSL - subroutines.)
      (WB 2001/01/30)

      diff --git a/deal.II/doc/news/6.3.0-vs-7.0.0.h b/deal.II/doc/news/6.3.0-vs-7.0.0.h index 6dc8e87c4b..df23b1594f 100644 --- a/deal.II/doc/news/6.3.0-vs-7.0.0.h +++ b/deal.II/doc/news/6.3.0-vs-7.0.0.h @@ -51,8 +51,7 @@ more naturally preserves consistency.
      As a consequence, if your makefile makes any assumption on the location of deal.II include files or the name of the deal.II library - it will need to be changed. The sample Makefiles have been + it will need to be changed. The sample Makefiles have been updated for this.
      (WB 2010/10/25) diff --git a/deal.II/doc/news/7.0.0-vs-7.1.0.h b/deal.II/doc/news/7.0.0-vs-7.1.0.h index 6d4ef48ce1..5e6decd05c 100644 --- a/deal.II/doc/news/7.0.0-vs-7.1.0.h +++ b/deal.II/doc/news/7.0.0-vs-7.1.0.h @@ -727,7 +727,7 @@ were not properly mapped. This is now fixed.
    • New: Restructured the internals of PETScWrappers::Precondition* to allow a PETSc PC object to exist without a solver. New: Use -Precondition*::vmult() to apply the preconditioner once. +Precondition*::%vmult() to apply the preconditioner once. Preconditioners now have a default constructor and an initialize() function and are no longer initialized in the solver call, but in the constructor or initialize(). diff --git a/deal.II/doc/news/7.2.0-vs-7.3.0.h b/deal.II/doc/news/7.2.0-vs-7.3.0.h index e40b25cb19..52808bccd7 100644 --- a/deal.II/doc/news/7.2.0-vs-7.3.0.h +++ b/deal.II/doc/news/7.2.0-vs-7.3.0.h @@ -224,7 +224,7 @@ that takes a std::vector (same interface as in Trilinos).
      (Timo Heister, 2013/02/19) -
    • New: PETScWrappers::*Matrix::add(other, factor) to +
    • New: PETScWrappers::*Matrix::%add(other, factor) to add a scaled other matrix to the current matrix.
      (Jose Javier Munoz Criollo, 2013/02/19) diff --git a/deal.II/doc/news/changes.h b/deal.II/doc/news/changes.h index 59758c9601..93d16b5ed8 100644 --- a/deal.II/doc/news/changes.h +++ b/deal.II/doc/news/changes.h @@ -1,5 +1,5 @@ /** - * @page changes_after_8_0 Changes after Version 8.0 +// * @page changes_after_8_0 Changes after Version 8.0

      This is the list of changes made after the release of @@ -24,7 +24,13 @@ inconvenience this causes.

        - +
      1. + Removed: The member function face_to_equivalent_cell_index() in + FiniteElementData has been removed. It had been deprecated a while + back already. Please use FiniteElement::face_to_cell_index() instead. +
        + (Wolfgang Bangerth, 2013/08/09) +
      @@ -35,6 +41,12 @@ inconvenience this causes.
        +
      1. + New: It is now possible to compile and link deal.II against LLVM's libcxx. For + this, a few issues with C++ standard violations are resolved. +
        + (Matthias Maier, 2013/08/09) +
      @@ -44,7 +56,145 @@ inconvenience this causes.

      Specific improvements

        - +
      1. + Fixed: Under some circumstances (see http://code.google.com/p/dealii/issues/detail?id=82) + the DoFTools::make_periodicity_constraints() function could create cycles in + the ConstraintMatrix object. This is now fixed. +
        + (David Emerson, Wolfgang Bangerth, 2013/08/16) +
      2. + +
      3. + New: There is now a function ConstraintMatrix::are_identity_constrained(). +
        + (Wolfgang Bangerth, 2013/08/16) +
      4. + +
      5. + New: TableHandler::write_text() now also supports output in + org-mode (http://orgmode.org/) format via a new entry in the + TableHandler::TextOutputFormat enumeration. +
        + (Oleh Krehel, 2013/08/15) +
      6. + +
      7. + New: There are now global functions scalar_product + that compute the scalar product (double contraction) between + tensors of rank 2. +
        + (Scott Miller, 2013/08/14) +
      8. + +
      9. + Fixed: Creating objects of type MappingQ was previously only possible + for low order polynomials. For orders higher than around 6, one ran + into assertions that tested for internal consistency. These assertions + have now been appropriately relaxes for the growth of round-off errors + with growing polynomial degrees. +
        + (Juan Carlos Araujo Cabarcas, Wolfgang Bangerth, 2013/08/14) +
      10. + +
      11. + New: MappingQEulerian is now also instantiated for vector elements + of type TrilinosWrappers::Vector as well as the MPI and block + variants. +
        + (Armin Ghajar Jazi, 2013/08/14) +
      12. + +
      13. + Fixed: The FiniteElement::face_to_cell_index() function had a bug + that made it work incorrectly for elements that have more than one + degree of freedom per line (in 2d) or per quad (in 3d). This is now + fixed for the most common cases, namely the FE_Q elements as well + as elements composed of FESystem elements. For all other cases, an + exception is generated reporting that this case is not implemented. + If you run into this, let us know. +
        + (Wolfgang Bangerth, 2013/08/10) +
      14. + +
      15. + New: DataOutBase::VtkFlags now has a flag + DataOutBase::VtkFlags::print_date_and_time that can be used to suppress output + of date and time in output files. This is useful in test suites where a newer + run at a different time produces differences against previously stored files, + even though the actual data is exactly the same. +
        + (Oleh Krehel, 2013/08/06) +
      16. + +
      17. + Fixed: The various block matrix classes are all derived from BlockMatrixBase + which had race conditions when the set() or add() functions were called from + different threads. This is now fixed. +
        + (Wolfgang Bangerth, 2013/08/05) +
      18. + +
      19. + Fixed: various fixes with assignment and reinit of PETScWrappers::MPI::Vector. +
        + (Timo Heister, 2013/08/05) +
      20. + +
      21. Fixed: An assertion wrongly triggered in + DoFTools::make_hanging_node_constraints when used with a particular + combination of FESystem elements containing FE_Nothing. This is now fixed. +
        + (Denis Davydov, Wolfgang Bangerth, 2013/08/01) +
      22. + +
      23. + New: Add has_ghost_elements() for PETScWrappers::MPI::BlockVector and + TrilinosWrappers::MPI::BlockVector. +
        + (Timo Heister, 2013/08/01) +
      24. + +
      25. + SparsityTools::distribute_sparsity_pattern did not work correctly for + block systems, this has been fixed (function has a different signature). +
        + (Timo Heister, 2013/07/31) +
      26. + +
      27. Fixed: When typing make run in the step-32 directory, + the program was executed with mpirun -np 2 ./step-32. This + assumes that a program mpirun exists, but also does that + deal.II was in fact compiled with MPI support on. Neither was intended. + This is now fixed. +
        + (Wolfgang Bangerth, 2013/07/24) +
      28. + +
      29. New: The DataOut, DataOutFaces, and DataOutRotation classes now allow + the output of data vectors using different DoFHandler objects (based on the + same triangulation), by new functions add_data_vector. This is used in the + step-31 tutorial program which avoids creating a joint DoFHandler just for + output. +
        + (Martin Kronbichler, 2013/07/24) +
      30. + +
      31. Changed: GridGenerator used to be a class with only static members + but is now a namespace, like all other similar constructs in deal.II. +
        + (Wolfgang Bangerth, 2013/07/24) +
      32. + +
      33. Changed: In GridGenerator, several functions had erroneously been changed + to take an argument of type size_type rather than unsigned + int. GridGenerator::size_type was a typedef to + types::global_dof_index, which for most users was unsigned int + anyway, but could also be set to be a 64-bit integer type. In any case, the + change has been reverted and these functions take just a regular + unsigned int again. +
        + (Wolfgang Bangerth, 2013/07/24) +
      diff --git a/deal.II/doc/news/news.html b/deal.II/doc/news/news.html index 79fa7929fb..bd812602cd 100644 --- a/deal.II/doc/news/news.html +++ b/deal.II/doc/news/news.html @@ -48,6 +48,10 @@ unknowns, and many more. A full list of changes can be found here. +
      + deal.II can be downloaded at + this site.
      @@ -894,9 +898,6 @@ library that, among much other functionality, offers some sparse direct solvers. We have added support for an interface to these solvers to the library. - (See the ReadMe - file for more information on installation of HSL - subroutines.)
      diff --git a/deal.II/doc/publications/index.html b/deal.II/doc/publications/index.html index eea2a46b95..4ce3eff9f5 100644 --- a/deal.II/doc/publications/index.html +++ b/deal.II/doc/publications/index.html @@ -429,6 +429,14 @@ Journal of Scientific Computing, vol. 55, pp. 432-454, 2013.
    • +
    • T. Fankhauser, T. Wihler, M. Wirz +
      + The hp-adaptive FEM based on continuous Sobolev embeddings: Isotropic + refinements +
      + Computers & Mathematics with Applications (in press), 2013. +
    • +
    • A. Geringer, B. Lenhof, S. Diebels
      Macroscopic modeling of foams: an order-parameter @@ -503,6 +511,14 @@ pp. 46-72, 2013.
    • +
    • N. Klein +
      + Consistent FE-Analysis of elliptic Variational Inequalities + +
      + PhD thesis, University of Siegen, Germany, 2013. +
    • +
    • T. Krüger
      Regularization-based fictitious domain methods @@ -739,6 +755,15 @@ a monolithic ALE framework pp. 114-124, 2013.
    • +
    • T. D. Young +
      + A finite basis grid analysis of the Hartree-Fock wavefunction method for one- and two-electron atoms + +
      + AIP Conf. Proc., Accepted, 2013. +
    • +
    • T. D. Young, E. Romero, J. E. Roman
      @@ -2898,12 +2923,7 @@ A Goal Oriented Software Library for Solving PDEs and Optimization Problems with basis

      - In George Maroulis and Theodore E. Simos, editors, - Computational Methods in Science and Engineering: Advances in - Computational Science, number 1108, New York, USA, Mar - 2009. Proceedings of the International Conference on Computational - Methods in Sciences and Engineering, American Institute of Physics - Conference Proceedings, 2009. + AIP Conf. Proc., vol. 1148, pp. 285-289 2009.
    • R. Ziegler, B. Brendel, A. Schipper, R. Harbers, M. van Beek, diff --git a/deal.II/doc/readme.html b/deal.II/doc/readme.html index 46a57e77da..b08a508c30 100644 --- a/deal.II/doc/readme.html +++ b/deal.II/doc/readme.html @@ -15,9 +15,9 @@

      - Note: Current development sources - use CMake to - build deal.II. For using the previous build + Note: deal.II uses + CMake to + configure and build. For using the previous build system used until deal.II version 7.3, see the old ReadMe file. @@ -224,7 +224,7 @@ mkdir build cd build - cmake -DCMAKE_INSTALL_PREFIX=/path/install/dir ../deal.II + cmake -DCMAKE_INSTALL_PREFIX=/path/to/install/dir ../deal.II make install

    These steps compile, link and install the deal.II library. The @@ -235,12 +235,13 @@

    Note:

      -
    • /path/install/dir is the directory which deal.II +
    • /path/to/install/dir is the directory which deal.II should be installed into. This can be a directory in your home directory (e.g., ~/bin/deal.II) or a directory such as /usr/local if you have root privileges. - Another option is to use `pwd`/../installed/ (note the - backticks). + Another option is to use something like `pwd`/../installed/ (note the + backticks). Make sure the installation directory is not the same + as the location where you unpacked deal.II/.
    • If your machine has multiple processors, use make -jN in the last step, where N is the diff --git a/deal.II/examples/step-1/step-1.cc b/deal.II/examples/step-1/step-1.cc index c887721bed..09599c7935 100644 --- a/deal.II/examples/step-1/step-1.cc +++ b/deal.II/examples/step-1/step-1.cc @@ -1,18 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 1999 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 1999 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + */ // @sect3{Include files} @@ -91,7 +93,7 @@ void second_grid () // We then fill it with a ring domain. The center of the ring shall be the // point (1,0), and inner and outer radius shall be 0.5 and 1. The number of // circumferential cells could be adjusted automatically by this function, - // but we choose to set it explicitely to 10 as the last argument: + // but we choose to set it explicitly to 10 as the last argument: const Point<2> center (1,0); const double inner_radius = 0.5, outer_radius = 1.0; diff --git a/deal.II/examples/step-10/step-10.cc b/deal.II/examples/step-10/step-10.cc index ca6507013b..f62c273b82 100644 --- a/deal.II/examples/step-10/step-10.cc +++ b/deal.II/examples/step-10/step-10.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2001 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2001 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Wolfgang Bangerth, Ralf Hartmann, University of Heidelberg, 2001 */ diff --git a/deal.II/examples/step-11/step-11.cc b/deal.II/examples/step-11/step-11.cc index c4f7647646..49cfda2b25 100644 --- a/deal.II/examples/step-11/step-11.cc +++ b/deal.II/examples/step-11/step-11.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2001 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2001 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 2001 */ diff --git a/deal.II/examples/step-12/step-12.cc b/deal.II/examples/step-12/step-12.cc index e50de11a6f..26c26d3acf 100644 --- a/deal.II/examples/step-12/step-12.cc +++ b/deal.II/examples/step-12/step-12.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2009 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2009 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Guido Kanschat, Texas A&M University, 2009 */ diff --git a/deal.II/examples/step-13/step-13.cc b/deal.II/examples/step-13/step-13.cc index 4334e90534..24ab2a6d5d 100644 --- a/deal.II/examples/step-13/step-13.cc +++ b/deal.II/examples/step-13/step-13.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2001 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2001 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 2001, 2002 */ @@ -170,7 +170,7 @@ namespace Step13 // macros. We use this mechanism here again. // // From this, the actual declaration of this class should be evident. Note - // that of course even if we do not list a destructor explicitely, an + // that of course even if we do not list a destructor explicitly, an // implicit destructor is generated from the compiler, and it is virtual // just as the one of the base class. template @@ -848,8 +848,8 @@ namespace Step13 // lead to deadlocks. A similar situation arises, when one changes // the code to have a return statement somewhere in the middle of // the locked block, and forgets that before we call - // return, we also have to unlock the mutex. This all - // is not be a problem here, but we want to show the general + // return, we also have to unlock the mutex. All this + // is no problem here, but we want to show the general // technique to cope with these problems nevertheless: have an // object that upon initialization (i.e. in its constructor) locks // the mutex, and on running the destructor unlocks it again. This diff --git a/deal.II/examples/step-14/step-14.cc b/deal.II/examples/step-14/step-14.cc index a8e2883368..f91bbfc666 100644 --- a/deal.II/examples/step-14/step-14.cc +++ b/deal.II/examples/step-14/step-14.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2002 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2002 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, ETH Zurich, 2002 */ @@ -2589,7 +2589,7 @@ namespace Step14 Assert (cell->neighbor(face_no).state() == IteratorState::valid, ExcInternalError()); // If we have that, then we need to find out with which face of the - // neighboring cell we have to work, i.e. the home-manythe + // neighboring cell we have to work, i.e. the how-many'th the // neighbor the present cell is of the cell behind the present face. For // this, there is a function, and we put the result into a variable with // the name neighbor_neighbor: @@ -2671,7 +2671,7 @@ namespace Step14 ExcInternalError()); // Then find out which neighbor the present cell is of the adjacent - // cell. Note that we will operator on the children of this adjacent + // cell. Note that we will operate on the children of this adjacent // cell, but that their orientation is the same as that of their mother, // i.e. the neigbor direction is the same. const unsigned int @@ -2836,7 +2836,7 @@ namespace Step14 // Finally, we have a variable that denotes the maximum number of // degrees of freedom we allow for the (primal) discretization. If it is - // exceeded, we stop the process of solving and intermittend mesh + // exceeded, we stop the process of solving and intermittent mesh // refinement. Its default value is 20,000. unsigned int max_degrees_of_freedom; diff --git a/deal.II/examples/step-15/doc/intro.dox b/deal.II/examples/step-15/doc/intro.dox index 33494379eb..344cd54f5f 100644 --- a/deal.II/examples/step-15/doc/intro.dox +++ b/deal.II/examples/step-15/doc/intro.dox @@ -95,7 +95,7 @@ u^{0}=g$ in the first step and with $\delta u^{n}=0$ in all the following steps.

      Weak formulation of the problem

      Starting with the strong formulation above, we get the weak formulation by multiplying -both sides of the PDE with a testfunction $\varphi$ and integrating by parts on both sides: +both sides of the PDE with a test function $\varphi$ and integrating by parts on both sides: @f[ \left( \nabla \varphi , \frac{1}{(1+|\nabla u^{n}|^{2})^{\frac{1}{2}}}\nabla \delta u^{n} \right)-\left(\nabla \varphi ,\frac{\nabla u^{n} \cdot \nabla @@ -112,7 +112,7 @@ Reducing this space to a finite dimensional space with basis $\left\{ \delta u^{n}=\sum_{j=0}^{N-1} U_{j} \varphi_{j} @f] -Using the basis functions as testfunctions and defining $a_{n}:=\frac{1} +Using the basis functions as test functions and defining $a_{n}:=\frac{1} {\sqrt{1+|\nabla u^{n}|^{2}}}$, we can rewrite the weak formualtion: @f[ diff --git a/deal.II/examples/step-15/step-15.cc b/deal.II/examples/step-15/step-15.cc index 4ec576c051..dca38227eb 100644 --- a/deal.II/examples/step-15/step-15.cc +++ b/deal.II/examples/step-15/step-15.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2012 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2012 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Sven Wetterauer, University of Heidelberg, 2012 */ @@ -81,7 +81,7 @@ namespace Step15 // $\delta u^n$, and one for the current iterate $u^n$. // - The setup_system function takes an argument that denotes whether // this is the first time it is called or not. The difference is that the - // first time around we need to distributed degrees of freedom and set the + // first time around we need to distribute the degrees of freedom and set the // solution vector for $u^n$ to the correct size. The following times, the // function is called after we have already done these steps as part of // refining the mesh in refine_mesh. @@ -267,12 +267,12 @@ namespace Step15 // For the assembly of the linear system, we have to obtain the values // of the previous solution's gradients at the quadrature // points. There is a standard way of doing this: the - // FEValues::get_function function takes a vector that represents a - // finite element field defined on a DoFHandler, and evaluates the - // gradients of this field at the quadrature points of the cell with - // which the FEValues object has last been reinitialized. The values - // of the gradients at all quadrature points are then written into the - // second argument: + // FEValues::get_function_gradients function takes a vector that + // represents a finite element field defined on a DoFHandler, and + // evaluates the gradients of this field at the quadrature points of the + // cell with which the FEValues object has last been reinitialized. + // The values of the gradients at all quadrature points are then written + // into the second argument: fe_values.get_function_gradients(present_solution, old_solution_gradients); @@ -520,7 +520,7 @@ namespace Step15 const unsigned int dofs_per_cell = fe.dofs_per_cell; const unsigned int n_q_points = quadrature_formula.size(); - Vector cell_rhs (dofs_per_cell); + Vector cell_residual (dofs_per_cell); std::vector > gradients(n_q_points); std::vector local_dof_indices (dofs_per_cell); @@ -530,7 +530,7 @@ namespace Step15 endc = dof_handler.end(); for (; cell!=endc; ++cell) { - cell_rhs = 0; + cell_residual = 0; fe_values.reinit (cell); // The actual computation is much as in @@ -549,7 +549,7 @@ namespace Step15 gradients[q_point]); for (unsigned int i = 0; i < dofs_per_cell; ++i) - cell_rhs(i) -= (fe_values.shape_grad(i, q_point) + cell_residual(i) -= (fe_values.shape_grad(i, q_point) * coeff * gradients[q_point] * fe_values.JxW(q_point)); @@ -557,7 +557,7 @@ namespace Step15 cell->get_dof_indices (local_dof_indices); for (unsigned int i=0; iMGConstraints knows - // it. So we simply ask for them by calling get_boundary_indices - // (). The third step is to construct constraints on all those + // boundary of each level. But this the MGConstraints knows. + // So we simply ask for them by calling get_boundary_indices(). + // The third step is to construct constraints on all those // degrees of freedom: their value should be zero after each application // of the level operators. To this end, we construct ConstraintMatrix // objects for each level, and add to each of these constraints for each diff --git a/deal.II/examples/step-17/CMakeLists.txt b/deal.II/examples/step-17/CMakeLists.txt index 77d825f29b..c32373d483 100644 --- a/deal.II/examples/step-17/CMakeLists.txt +++ b/deal.II/examples/step-17/CMakeLists.txt @@ -34,7 +34,7 @@ IF(NOT DEAL_II_WITH_PETSC) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_PETSC = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-17/step-17.cc b/deal.II/examples/step-17/step-17.cc index 43e274a2b6..0b9499c848 100644 --- a/deal.II/examples/step-17/step-17.cc +++ b/deal.II/examples/step-17/step-17.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2000 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2000 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Texas at Austin, 2000, 2004 */ @@ -245,10 +245,11 @@ namespace Step17 // communicator object that only links a subset of all processes), and call // the Utilities helper functions to determine the number of processes and // where the present one fits into this picture. In addition, we make sure - // that output is only generated by the (globally) first process. As, - // this_mpi_process is determined after creation of pcout, we cannot set the - // condition through the constructor, i.e. by pcout(std::cout, - // this_mpi_process==0), but set the condition separately. + // that output is only generated by the (globally) first process. As + // this_mpi_process is determined after creation of pcout, we + // cannot set the condition through the constructor, i.e. by + // pcout(std::cout, this_mpi_process==0), but set the + // condition separately. template ElasticProblem::ElasticProblem () : @@ -537,7 +538,7 @@ namespace Step17 // The last argument to the call just performed allows for some // optimizations. It controls whether we should also delete the column // corresponding to a boundary node, or keep it (and passing - // true as above means: yes, do eliminate the column). If we + // true means: yes, do eliminate the column). If we // do, then the resulting matrix will be symmetric again if it was before; // if we don't, then it won't. The solution of the resulting system should // be the same, though. The only reason why we may want to make the system diff --git a/deal.II/examples/step-18/CMakeLists.txt b/deal.II/examples/step-18/CMakeLists.txt index c1e1076991..33af07ee5a 100644 --- a/deal.II/examples/step-18/CMakeLists.txt +++ b/deal.II/examples/step-18/CMakeLists.txt @@ -34,7 +34,7 @@ IF(NOT DEAL_II_WITH_PETSC) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_PETSC = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-18/doc/intro.dox b/deal.II/examples/step-18/doc/intro.dox index 2c37a1d863..81ff567e44 100644 --- a/deal.II/examples/step-18/doc/intro.dox +++ b/deal.II/examples/step-18/doc/intro.dox @@ -107,7 +107,7 @@ following, let us consider some of the tools one would employ when simulating problems in which the deformation becomes large. @note The model we will consider below is not founded on anything that -would be mathematical sound: we will consider a model in which we +would be mathematically sound: we will consider a model in which we produce a small deformation, deform the physical coordinates of the body by this deformation, and then consider the next loading step again as a linear problem. This isn't consistent, since the assumption diff --git a/deal.II/examples/step-18/doc/results.dox b/deal.II/examples/step-18/doc/results.dox index 7c3c022825..b59460a793 100644 --- a/deal.II/examples/step-18/doc/results.dox +++ b/deal.II/examples/step-18/doc/results.dox @@ -111,10 +111,10 @@ examples/\step-18> ../\step-19/\step-19 Converter from deal.II intermediate format to other graphics formats. -Usage: ./\step-19 [-p parameter_file] list_of_input_files [-x output_format] output_file +Usage: ./\step-19 [-p parameter_file] list_of_input_files [-x output_format] -o output_file -examples/\step-18> ../\step-19/\step-19 solution-0001.0000.d2 -x gmv solution-0001.0000.gmv -examples/\step-18> ../\step-19/\step-19 solution-0002.0000.d2 -x gmv solution-0002.0000.gmv +examples/\step-18> ../\step-19/\step-19 solution-0001.0000.d2 -x gmv -o solution-0001.0000.gmv +examples/\step-18> ../\step-19/\step-19 solution-0002.0000.d2 -x gmv -o solution-0002.0000.gmv [...] @endcode Of course, since we have run the program only in sequential mode, we diff --git a/deal.II/examples/step-18/step-18.cc b/deal.II/examples/step-18/step-18.cc index 34ed6cb280..9de024169a 100644 --- a/deal.II/examples/step-18/step-18.cc +++ b/deal.II/examples/step-18/step-18.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2000 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2000 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Texas at Austin, 2000, 2004, 2005 */ @@ -106,8 +106,8 @@ namespace Step18 // in the form $C_{ijkl} = \mu (\delta_{ik} \delta_{jl} + \delta_{il} // \delta_{jk}) + \lambda \delta_{ij} \delta_{kl}$. This tensor maps // symmetric tensor of rank 2 to symmetric tensors of rank 2. A function - // implementing its creation for given values of the Lame constants lambda - // and mu is straightforward: + // implementing its creation for given values of the Lame constants $\lambda$ + // and $\mu$ is straightforward: template SymmetricTensor<4,dim> get_stress_strain_tensor (const double lambda, const double mu) @@ -443,7 +443,7 @@ namespace Step18 // One difference of this program is that we declare the quadrature // formula in the class declaration. The reason is that in all the other // programs, it didn't do much harm if we had used different quadrature - // formulas when computing the matrix and the righ hand side, for + // formulas when computing the matrix and the right hand side, for // example. However, in the present case it does: we store information in // the quadrature points, so we have to make sure all parts of the program // agree on where they are and how many there are on each cell. Thus, let @@ -1330,10 +1330,10 @@ namespace Step18 subdomain_id (subdomain_id) {} - virtual typename DoFHandler::cell_iterator + virtual typename DataOut::cell_iterator first_cell () { - typename DoFHandler::active_cell_iterator + typename DataOut::active_cell_iterator cell = this->dofs->begin_active(); while ((cell != this->dofs->end()) && (cell->subdomain_id() != subdomain_id)) @@ -1342,8 +1342,8 @@ namespace Step18 return cell; } - virtual typename DoFHandler::cell_iterator - next_cell (const typename DoFHandler::cell_iterator &old_cell) + virtual typename DataOut::cell_iterator + next_cell (const typename DataOut::cell_iterator &old_cell) { if (old_cell != this->dofs->end()) { @@ -1352,7 +1352,7 @@ namespace Step18 return ++(FilteredIterator - ::active_cell_iterator> + ::active_cell_iterator> (predicate,old_cell)); } else @@ -1456,7 +1456,7 @@ namespace Step18 // As a last piece of data, let us also add the partitioning of the domain // into subdomains associated with the processors if this is a parallel // job. This works in the exact same way as in the step-17 program: - std::vector partition_int (triangulation.n_active_cells()); + std::vector partition_int (triangulation.n_active_cells()); GridTools::get_subdomain_association (triangulation, partition_int); const Vector partitioning(partition_int.begin(), partition_int.end()); diff --git a/deal.II/examples/step-19/step-19.cc b/deal.II/examples/step-19/step-19.cc index 6f8b667281..17bec2c4ab 100644 --- a/deal.II/examples/step-19/step-19.cc +++ b/deal.II/examples/step-19/step-19.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2005 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2005 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Luca Heltai, Wolfgang Bangerth, 2005 */ @@ -297,7 +297,7 @@ namespace Step19 prm.get_bool ("Dummy generate output"); } prm.leave_subsection (); - // We would assign the result to a variable, or course, but don't + // We would assign the result to a variable, of course, but don't // here in order not to generate an unused variable that the // compiler might warn about. // diff --git a/deal.II/examples/step-2/step-2.cc b/deal.II/examples/step-2/step-2.cc index 1747f1db35..cb6cd25b2e 100644 --- a/deal.II/examples/step-2/step-2.cc +++ b/deal.II/examples/step-2/step-2.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 1999 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 1999 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 1999 */ diff --git a/deal.II/examples/step-20/step-20.cc b/deal.II/examples/step-20/step-20.cc index e71fa739e8..a0e6c251d8 100644 --- a/deal.II/examples/step-20/step-20.cc +++ b/deal.II/examples/step-20/step-20.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2005 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2005 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, Texas A&M University, 2005, 2006 */ diff --git a/deal.II/examples/step-21/step-21.cc b/deal.II/examples/step-21/step-21.cc index fbf4aee19e..24c95d3bef 100644 --- a/deal.II/examples/step-21/step-21.cc +++ b/deal.II/examples/step-21/step-21.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2006 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2006 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Yan Li, Wolfgang Bangerth, Texas A&M University, 2006 */ diff --git a/deal.II/examples/step-22/CMakeLists.txt b/deal.II/examples/step-22/CMakeLists.txt index 00923478ae..03e2ef3408 100644 --- a/deal.II/examples/step-22/CMakeLists.txt +++ b/deal.II/examples/step-22/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_UMFPACK) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_UMFPACK = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-22/doc/intro.dox b/deal.II/examples/step-22/doc/intro.dox index 73a5674dac..b57dbed1ba 100644 --- a/deal.II/examples/step-22/doc/intro.dox +++ b/deal.II/examples/step-22/doc/intro.dox @@ -566,7 +566,7 @@ struct InnerPreconditioner<3> @endcode From hereon, we can refer to the type typename -InnerPreconditioner@::type and automatically get the correct +InnerPreconditioner@::%type and automatically get the correct preconditioner class. Because of the similarity of the interfaces of the two classes, we will be able to use them interchangeably using the same syntax in all places. diff --git a/deal.II/examples/step-22/doc/results.dox b/deal.II/examples/step-22/doc/results.dox index 3524d69293..5263299127 100644 --- a/deal.II/examples/step-22/doc/results.dox +++ b/deal.II/examples/step-22/doc/results.dox @@ -119,7 +119,7 @@ This plot uses the capability of VTK-based visualization programs (in this case of VisIt) to show vector data; this is the result of us declaring the velocity components of the finite element in use to be a set of vector components, rather than independent scalar components in -the StokesProblem@::output_results function of this +the StokesProblem@::%output_results function of this tutorial program. diff --git a/deal.II/examples/step-22/step-22.cc b/deal.II/examples/step-22/step-22.cc index 1fcf3b5a3b..96ea2b0427 100644 --- a/deal.II/examples/step-22/step-22.cc +++ b/deal.II/examples/step-22/step-22.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2008 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2008 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, Texas A&M University, 2008 */ diff --git a/deal.II/examples/step-23/doc/intro.dox b/deal.II/examples/step-23/doc/intro.dox index c7b70487af..1139efd2bd 100644 --- a/deal.II/examples/step-23/doc/intro.dox +++ b/deal.II/examples/step-23/doc/intro.dox @@ -84,7 +84,7 @@ other time dependent problems, we find that the character of a solution changes as time progresses. For example, for the wave equation, we may have a single wave travelling through the domain, where the solution is smooth or even constant in front of and behind -the wave &mdash& adaptivity would be really useful for such cases, but the +the wave — adaptivity would be really useful for such cases, but the key is that the area where we need to refine the mesh changes from time step to time step! @@ -156,7 +156,7 @@ time derivatives for both variables, for which it is simple to write down time stepping schemes. Note that we do not have boundary conditions for $v$ at first. However, we could enforce $v=\frac{\partial g}{\partial t}$ on the boundary. It turns out in numerical examples that this -as actually necessary: without doing so the solution doesn't look particularly +is actually necessary: without doing so the solution doesn't look particularly wrong, but the Crank-Nicolson scheme does not conserve energy if one doesn't enforce these boundary conditions. @@ -296,9 +296,9 @@ where \\ A^{n,n-1}_{ij} &=& (\nabla\phi_i^n, \nabla\phi_j^{n-1}), \\ - F^n_{ij} &=& (f^n,\phi_i^n), + F^n_{i} &=& (f^n,\phi_i^n), \\ - F^{n-1}_{ij} &=& (f^{n-1},\phi_i^n). + F^{n-1}_{i} &=& (f^{n-1},\phi_i^n). @f} If we solve these two equations, we can move the solution one step diff --git a/deal.II/examples/step-23/doc/results.dox b/deal.II/examples/step-23/doc/results.dox index 513699f9f9..1c86e3eb7d 100644 --- a/deal.II/examples/step-23/doc/results.dox +++ b/deal.II/examples/step-23/doc/results.dox @@ -105,8 +105,8 @@ If you want to explore a bit, try out some of the following things: To make such a change, we would have to compute the mass and Laplace matrices with a variable coefficient. Fortunately, this isn't too hard: the - functions MatrixTools::create_laplace_matrix and - MatrixTools::create_vector_tools have additional default parameters that can + functions MatrixCreator::create_laplace_matrix and + MatrixCreator::create_mass_matrix have additional default parameters that can be used to pass non-constant coefficient functions to them. The required changes are therefore relatively small. On the other hand, care must be taken again to make sure the time step is within the allowed range. diff --git a/deal.II/examples/step-23/step-23.cc b/deal.II/examples/step-23/step-23.cc index 628f840f7a..3fb30e3476 100644 --- a/deal.II/examples/step-23/step-23.cc +++ b/deal.II/examples/step-23/step-23.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2006 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2006 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, Texas A&M University, 2006 */ @@ -54,7 +54,7 @@ // Here are the only three include files of some new interest: The first one // is already used, for example, for the // VectorTools::interpolate_boundary_values and -// VectorTools::apply_boundary_values functions. However, we here use another +// MatrixTools::apply_boundary_values functions. However, we here use another // function in that class, VectorTools::project to compute our initial values // as the $L^2$ projection of the continuous initial values. Furthermore, we // use VectorTools::create_right_hand_side to generate the integrals @@ -68,8 +68,8 @@ // mass and Laplace matrices, although it would have only taken copying the // relevant code from any number of previous tutorial programs. Rather, we // want to focus on the things that are truly new to this program and -// therefore use the MatrixTools::create_mass_matrix and -// MatrixTools::create_laplace_matrix functions. They are declared here: +// therefore use the MatrixCreator::create_mass_matrix and +// MatrixCreator::create_laplace_matrix functions. They are declared here: #include // Finally, here is an include file that contains all sorts of tool functions diff --git a/deal.II/examples/step-24/doc/intro.dox b/deal.II/examples/step-24/doc/intro.dox index 4ee0f37f70..c3a23332cc 100644 --- a/deal.II/examples/step-24/doc/intro.dox +++ b/deal.II/examples/step-24/doc/intro.dox @@ -118,7 +118,7 @@ defined as the derivative of the pressure potential: v = \frac{\partial\bar{p}}{\partial t} @f] -With the second variables, one then transform the forward problem into +With the second variable, one then transforms the forward problem into two separate equations: @f{eqnarray*} \bar{p}_{t} - v & = & 0 \\ diff --git a/deal.II/examples/step-24/step-24.cc b/deal.II/examples/step-24/step-24.cc index ccf969d74d..e44ea21f12 100644 --- a/deal.II/examples/step-24/step-24.cc +++ b/deal.II/examples/step-24/step-24.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2006 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2006 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Xing Jin, Wolfgang Bangerth, Texas A&M University, 2006 */ @@ -132,7 +132,7 @@ namespace Step24 // pressure. In the physical setting considered in this program, these are // small absorbers, which we model as a series of little circles where we // assume that the pressure surplus is one, whereas no absorption and - // therefore no pressure surplus is anywhere else. This is how we do things + // therefore no pressure surplus is everywhere else. This is how we do things // (note that if we wanted to expand this program to not only compile but // also to run, we would have to initialize the sources with // three-dimensional source locations): @@ -311,7 +311,7 @@ namespace Step24 // // A first observation would be that this matrix is much sparser than the // regular mass matrix, since none of the shape functions with purely - // interior support contributes to this matrix. We could therefore + // interior support contribute to this matrix. We could therefore // optimize the storage pattern to this situation and build up a second // sparsity pattern that only contains the nonzero entries that we // need. There is a trade-off to make here: first, we would have to have a @@ -475,7 +475,7 @@ namespace Step24 // consumption of the program, the introduction of a few temporary vectors // isn't doing much harm. // - // The only changes to this function are: First, that we do not have to + // The only changes to this function are: first, that we do not have to // project initial values for the velocity $v$, since we know that it is // zero. And second that we evaluate the solution at the detector locations // computed in the constructor. This is done using the diff --git a/deal.II/examples/step-25/doc/intro.dox b/deal.II/examples/step-25/doc/intro.dox index f43b6a3178..96f269cc3a 100644 --- a/deal.II/examples/step-25/doc/intro.dox +++ b/deal.II/examples/step-25/doc/intro.dox @@ -101,8 +101,8 @@ To this end, we can use Newton's method. Given the nonlinear equation $F(u^n) = \mbox{ Find } \delta u^n_l \mbox{ s.t. } F'(u^n_l)\delta u^n_l = -F(u^n_l) \mbox{, set } u^n_{l+1} = u^n_l + \delta u^n_l. \f} -The iteration can be initialized with the old time step, i.e. $u^{n,0} = -u^{n-1}$, and eventually it will produce a solution to the first equation of +The iteration can be initialized with the old time step, i.e. $u^n_0 = u^{n-1}$, +and eventually it will produce a solution to the first equation of the split formulation (see above). For the time discretizaion of the sine-Gordon equation under consideration here, we have that \f{eqnarray*} @@ -120,7 +120,7 @@ With hindsight, we choose both the solution and the test space to be $H^1(\Omega &\mbox{ Find}& \delta u^n_l \in H^1(\Omega) \mbox{ s.t. } \left( F'(u^n_l)\delta u^n_l, \varphi \right)_{\Omega} = -\left(F(u^n_l), \varphi \right)_{\Omega} \;\forall\varphi\in H^1(\Omega), - \mbox{ set } u^n_{l+1} = u^n_l + \delta u^n_l,\; u^{n,0} = u^{n-1}.\\ + \mbox{ set } u^n_{l+1} = u^n_l + \delta u^n_l,\; u^n_0 = u^{n-1}.\\ &\mbox{ Find}& v^n \in H^1(\Omega) \mbox{ s.t. } \left( v^n, \varphi \right)_{\Omega} = \left( v^{n-1}, \varphi \right)_{\Omega} - k\theta\left( \nabla u^n, \nabla\varphi \right)_{\Omega} @@ -157,9 +157,9 @@ Above, the matrix $F_h'(\cdot)$ and the vector $F_h(\cdot)$ denote the discrete \f{eqnarray*} F_h(U^{n,l}) &=& \left[ M+k^2\theta^2A \right] U^{n,l} - \left[ M-k^2\theta(1-\theta)A \right] U^{n-1} - k MV^{n-1} - + k^2\theta S(u^{n,l}, u^{n-1}),\\ + + k^2\theta S(u^n_l, u^{n-1}),\\ F_h'(U^{n,l}) &=& M+k^2\theta^2A - - k^2\theta^2N(u^{n,l},u^{n-1}) + - k^2\theta^2N(u^n_l,u^{n-1}) \f} Again, note that the first matrix equation above is, in fact, the defition of an iterative procedure, so it is solved multiple times @@ -176,9 +176,9 @@ i.e. $N_{ij}(f,g) = \left( \cos\left[ \theta f + (1-\theta) g\right]\varphi_i, What solvers can we use for the first equation? Let's look at the matrix we have to invert: @f[ - (M-k^2\theta^2N)_{ij} = + (M+k^2\theta^2(A-N))_{ij} = \int_\Omega (1-k^2\theta^2 \cos \alpha) - \varphi_i\varphi_j \; dx, + \varphi_i\varphi_j \; dx+\int_\Omega \nabla\varphi_i\nabla\varphi_j \; dx, @f] for some $\alpha$ that depends on the present and previous solution. First, note that the matrix is symmetric. In addition, if the time step $k$ is small diff --git a/deal.II/examples/step-25/step-25.cc b/deal.II/examples/step-25/step-25.cc index a03335ce34..794e09f870 100644 --- a/deal.II/examples/step-25/step-25.cc +++ b/deal.II/examples/step-25/step-25.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2006 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2006 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Ivan Christov, Wolfgang Bangerth, Texas A&M University, 2006 */ @@ -333,7 +333,7 @@ namespace Step25 // @sect4{SineGordonProblem::assemble_system} - // This functions assembles the system matrix and right-hand side vector for + // This function assembles the system matrix and right-hand side vector for // each iteration of Newton's method. The reader should refer to the // Introduction for the explicit formulas for the system matrix and // right-hand side. @@ -350,7 +350,6 @@ namespace Step25 { // First we assemble the Jacobian matrix $F'_h(U^{n,l})$, where $U^{n,l}$ // is stored in the vector solution for convenience. - system_matrix = 0; system_matrix.copy_from (mass_matrix); system_matrix.add (std::pow(time_step*theta,2), laplace_matrix); @@ -359,9 +358,23 @@ namespace Step25 system_matrix.add (-std::pow(time_step*theta,2), tmp_matrix); // Then, we compute the right-hand side vector $-F_h(U^{n,l})$. + // + // We have to first build up the matrix + // $M+k^2\theta^2 A$, which we put into tmp_matrix + // use it to compute a contribution to the right hand side vector, and + // then build the matrix $M-k^2\theta(1-\theta) A$. We could + // build it in the same way as before, i.e., using code like + // @code + // tmp_matrix.copy_from (mass_matrix); + // tmp_matrix.add (-std::pow(time_step,2)*theta*(1-theta), laplace_matrix); + // @endcode + // but we can save the expense of the copy_from operation + // by starting from what is already in the tmp_matrix + // variable (i.e., $M+k^2\theta^2 A$) and subtracting from this + // $k^2\theta^2 A+k^2\theta(1-\theta) A=k^2\theta A$ when computing the + // second matrix: system_rhs = 0; - tmp_matrix = 0; tmp_matrix.copy_from (mass_matrix); tmp_matrix.add (std::pow(time_step*theta,2), laplace_matrix); @@ -369,17 +382,14 @@ namespace Step25 tmp_matrix.vmult (tmp_vector, solution); system_rhs += tmp_vector; - tmp_matrix = 0; - tmp_matrix.copy_from (mass_matrix); - tmp_matrix.add (-std::pow(time_step,2)*theta*(1-theta), laplace_matrix); - tmp_vector = 0; + tmp_matrix.add(-std::pow(time_step, 2) * theta, laplace_matrix); + tmp_matrix.vmult (tmp_vector, old_solution); system_rhs -= tmp_vector; system_rhs.add (-time_step, M_x_velocity); - tmp_vector = 0; compute_nl_term (old_solution, solution, tmp_vector); system_rhs.add (std::pow(time_step,2)*theta, tmp_vector); @@ -413,6 +423,7 @@ namespace Step25 const Vector &new_data, Vector &nl_term) const { + nl_term = 0; const QGauss quadrature_formula (3); FEValues fe_values (fe, quadrature_formula, update_values | @@ -433,6 +444,7 @@ namespace Step25 for (; cell!=endc; ++cell) { + local_nl_term = 0; // Once we re-initialize our FEValues instantiation to // the current cell, we make use of the // get_function_values routine to get the values of the @@ -459,8 +471,6 @@ namespace Step25 for (unsigned int i=0; iFEValues // instantiation to the current cell. fe_values.reinit (cell); @@ -521,8 +532,6 @@ namespace Step25 for (unsigned int j=0; j preconditioner; preconditioner.initialize(system_matrix, 1.2); - solution_update = 0; cg.solve (system_matrix, solution_update, system_rhs, preconditioner); @@ -686,11 +694,9 @@ namespace Step25 laplace_matrix.vmult (tmp_vector, solution); M_x_velocity.add (-time_step*theta, tmp_vector); - tmp_vector = 0; laplace_matrix.vmult (tmp_vector, old_solution); M_x_velocity.add (-time_step*(1-theta), tmp_vector); - tmp_vector = 0; compute_nl_term (old_solution, solution, tmp_vector); M_x_velocity.add (-time_step, tmp_vector); diff --git a/deal.II/examples/step-26/step-26.cc b/deal.II/examples/step-26/step-26.cc index 23c2250e1e..2e16d32ad2 100644 --- a/deal.II/examples/step-26/step-26.cc +++ b/deal.II/examples/step-26/step-26.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, Texas A&M University, 2013 */ diff --git a/deal.II/examples/step-27/step-27.cc b/deal.II/examples/step-27/step-27.cc index 4f9bc6680f..1a4beaca1f 100644 --- a/deal.II/examples/step-27/step-27.cc +++ b/deal.II/examples/step-27/step-27.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2006 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2006 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, Texas A&M University, 2006, 2007 */ diff --git a/deal.II/examples/step-28/doc/intro.dox b/deal.II/examples/step-28/doc/intro.dox index 179a8fa239..b7076cbc86 100644 --- a/deal.II/examples/step-28/doc/intro.dox +++ b/deal.II/examples/step-28/doc/intro.dox @@ -179,7 +179,7 @@ one. A stable reactor should have $k_{\mathrm{eff}}=1$. [For those who wonder how this can be achieved in practice without inadvertently getting slightly larger than one and triggering a nuclear bomb: first, fission processes happen on different time scales. While most neutrons -are releases very quickly after a fission event, a small number of neutrons +are released very quickly after a fission event, a small number of neutrons are only released by daughter nuclei after several further decays, up to 10-60 seconds after the fission was initiated. If one is therefore slightly beyond $k_{\mathrm{eff}}=1$, one therefore has many seconds to react until all the @@ -431,7 +431,7 @@ these three cases, as follows:
    • If the cell $K$ is active on mesh $g$, but not $g'$, then the basis functions $\varphi_{g'}^j$ are only defined either on the children $K_c,0\le c<2^{\texttt{dim}}$, or on children of these children if cell $K$ - is refined more than once more on mesh $g'$. + is refined more than once on mesh $g'$. Let us assume for a second that $K$ is only once more refined on mesh $g'$ than on mesh $g$. Using the fact that we use embedded finite element spaces diff --git a/deal.II/examples/step-28/step-28.cc b/deal.II/examples/step-28/step-28.cc index 14ac1ba6be..f4365766fd 100644 --- a/deal.II/examples/step-28/step-28.cc +++ b/deal.II/examples/step-28/step-28.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2009 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2009 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Yaqi Wang, Texas A&M University, 2009, 2010 */ diff --git a/deal.II/examples/step-29/CMakeLists.txt b/deal.II/examples/step-29/CMakeLists.txt index 14a0f1000d..6872bc4bfb 100644 --- a/deal.II/examples/step-29/CMakeLists.txt +++ b/deal.II/examples/step-29/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_UMFPACK) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_UMFPACK = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-29/doc/intro.dox b/deal.II/examples/step-29/doc/intro.dox index 73cd997c5e..03f347e791 100644 --- a/deal.II/examples/step-29/doc/intro.dox +++ b/deal.II/examples/step-29/doc/intro.dox @@ -38,7 +38,7 @@ toplevel overview of this topic can be found in the @ref vector_valued module. The original purpose of this program is to simulate the focussing properties of an ultrasound wave generated by a transducer lens with variable geometry. Recent applications in medical imaging use ultrasound waves not only -for imaging porposes, but also to excite certain local effects in a +for imaging purposes, but also to excite certain local effects in a material, like changes in optical properties, that can then be measured by other imaging techniques. A vital ingredient for these methods is the ability to focus the intensity of the ultrasound wave in a particular part of the @@ -180,7 +180,7 @@ of the circle with center at $(0.5, d)$ and a radius slightly greater than $d$; this shape should lead to a focusing of the sound wave at the center of the circle. Varying $d$ changes the "focus" of the lens and affects the spatial distribution of the intensity of $u$, where our main -concern is how well $|u|=\sqrt{v^2+w^2}$ is.focussed. +concern is how well $|u|=\sqrt{v^2+w^2}$ is focussed. In the program below, we will implement the complex-valued Helmholtz equations using the formulation with split real and imaginary parts. We will also diff --git a/deal.II/examples/step-29/step-29.cc b/deal.II/examples/step-29/step-29.cc index d955cd261e..9c3360572b 100644 --- a/deal.II/examples/step-29/step-29.cc +++ b/deal.II/examples/step-29/step-29.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2007 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2007 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Moritz Allmaras, Texas A&M University, 2007 */ @@ -367,7 +367,7 @@ namespace Step29 ExcDimensionMismatch (computed_quantities[i].size(), 1)); Assert(uh[i].size() == 2, ExcDimensionMismatch (uh[i].size(), 2)); - computed_quantities[i](0) = sqrt(uh[i](0)*uh[i](0) + uh[i](1)*uh[i](1)); + computed_quantities[i](0) = std::sqrt(uh[i](0)*uh[i](0) + uh[i](1)*uh[i](1)); } } diff --git a/deal.II/examples/step-3/step-3.cc b/deal.II/examples/step-3/step-3.cc index 884be34c03..f6ab655810 100644 --- a/deal.II/examples/step-3/step-3.cc +++ b/deal.II/examples/step-3/step-3.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 1999 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 1999 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Wolfgang Bangerth, 1999, * Guido Kanschat, 2011 */ diff --git a/deal.II/examples/step-30/step-30.cc b/deal.II/examples/step-30/step-30.cc index 5e50d7316a..bb1397c71c 100644 --- a/deal.II/examples/step-30/step-30.cc +++ b/deal.II/examples/step-30/step-30.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2007 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2007 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Tobias Leicht, 2007 */ diff --git a/deal.II/examples/step-31/CMakeLists.txt b/deal.II/examples/step-31/CMakeLists.txt index 645efcfc55..f21c9612ea 100644 --- a/deal.II/examples/step-31/CMakeLists.txt +++ b/deal.II/examples/step-31/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_TRILINOS) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_TRILINOS = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-31/step-31.cc b/deal.II/examples/step-31/step-31.cc index e8d0062099..0d33264c19 100644 --- a/deal.II/examples/step-31/step-31.cc +++ b/deal.II/examples/step-31/step-31.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2007 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2007 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Martin Kronbichler, Uppsala University, * Wolfgang Bangerth, Texas A&M University 2007, 2008 */ @@ -1918,133 +1918,42 @@ namespace Step31 // This function writes the solution to a VTK output file for visualization, // which is done every tenth time step. This is usually quite a simple task, // since the deal.II library provides functions that do almost all the job - // for us. In this case, the situation is a bit more complicated, since we - // want to visualize both the Stokes solution and the temperature as one - // data set, but we have done all the calculations based on two different - // DoFHandler objects, a situation the DataOut class usually used for output - // is not prepared to deal with. The way we're going to achieve this - // recombination is to create a joint DoFHandler that collects both - // components, the Stokes solution and the temperature solution. This can be - // nicely done by combining the finite elements from the two systems to form - // one FESystem, and let this collective system define a new DoFHandler - // object. To be sure that everything was done correctly, we perform a - // sanity check that ensures that we got all the dofs from both Stokes and - // temperature even in the combined system. - // - // Next, we create a vector that will collect the actual solution - // values. Since this vector is only going to be used for output, we create - // it as a deal.II vector that nicely cooperate with the data output - // classes. Remember that we used Trilinos vectors for assembly and solving. + // for us. There is one new function compared to previous examples: We want + // to visualize both the Stokes solution and the temperature as one data + // set, but we have done all the calculations based on two different + // DoFHandler objects. Luckily, the DataOut class is prepared to deal with + // it. All we have to do is to not attach one single DoFHandler at the + // beginning and then use that for all added vector, but specify the + // DoFHandler to each vector separately. The rest is done as in step-22. We + // create solution names (that are going to appear in the visualization + // program for the individual components). The first dim + // components are the vector velocity, and then we have pressure for the + // Stokes part, whereas temperature is scalar. This information is read out + // using the DataComponentInterpretation helper class. Next, we actually + // attach the data vectors with their DoFHandler objects, build patches + // according to the degree of freedom, which are (sub-) elements that + // describe the data for visualization programs. Finally, we set a file name + // (that includes the time step number) and write the vtk file. template void BoussinesqFlowProblem::output_results () const { if (timestep_number % 10 != 0) return; - const FESystem joint_fe (stokes_fe, 1, - temperature_fe, 1); - DoFHandler joint_dof_handler (triangulation); - joint_dof_handler.distribute_dofs (joint_fe); - Assert (joint_dof_handler.n_dofs() == - stokes_dof_handler.n_dofs() + temperature_dof_handler.n_dofs(), - ExcInternalError()); - - Vector joint_solution (joint_dof_handler.n_dofs()); - - // Unfortunately, there is no straight-forward relation that tells us how - // to sort Stokes and temperature vector into the joint vector. The way we - // can get around this trouble is to rely on the information collected in - // the FESystem. For each dof in a cell, the joint finite element knows to - // which equation component (velocity component, pressure, or temperature) - // it belongs – that's the information we need! So we step through - // all cells (with iterators into all three DoFHandlers moving in synch), - // and for each joint cell dof, we read out that component using the - // FiniteElement::system_to_base_index function (see there for a - // description of what the various parts of its return value contain). We - // also need to keep track whether we're on a Stokes dof or a temperature - // dof, which is contained in - // joint_fe.system_to_base_index(i).first.first. Eventually, - // the dof_indices data structures on either of the three systems tell us - // how the relation between global vector and local dofs looks like on the - // present cell, which concludes this tedious work. - // - // There's one thing worth remembering when looking at the output: In our - // algorithm, we first solve for the Stokes system at time level - // n-1 in each time step and then for the temperature at time level - // n using the previously computed velocity. These are the two - // components we join for output, so these two parts of the output file - // are actually misaligned by one time step. Since we consider graphical - // output as only a qualititative means to understand a solution, we - // ignore this $\mathcal{O}(h)$ error. - { - std::vector local_joint_dof_indices (joint_fe.dofs_per_cell); - std::vector local_stokes_dof_indices (stokes_fe.dofs_per_cell); - std::vector local_temperature_dof_indices (temperature_fe.dofs_per_cell); - - typename DoFHandler::active_cell_iterator - joint_cell = joint_dof_handler.begin_active(), - joint_endc = joint_dof_handler.end(), - stokes_cell = stokes_dof_handler.begin_active(), - temperature_cell = temperature_dof_handler.begin_active(); - for (; joint_cell!=joint_endc; ++joint_cell, ++stokes_cell, ++temperature_cell) - { - joint_cell->get_dof_indices (local_joint_dof_indices); - stokes_cell->get_dof_indices (local_stokes_dof_indices); - temperature_cell->get_dof_indices (local_temperature_dof_indices); - - for (unsigned int i=0; idim components are the vector velocity, - // and then we have pressure and temperature. This information is read out - // using the DataComponentInterpretation helper class. Next, we attach the - // solution values together with the names of its components to the output - // object, and build patches according to the degree of freedom, which are - // (sub-) elements that describe the data for visualization - // programs. Finally, we set a file name (that includes the time step - // number) and write the vtk file. - std::vector joint_solution_names (dim, "velocity"); - joint_solution_names.push_back ("p"); - joint_solution_names.push_back ("T"); - - DataOut data_out; - - data_out.attach_dof_handler (joint_dof_handler); - + std::vector stokes_names (dim, "velocity"); + stokes_names.push_back ("p"); std::vector - data_component_interpretation - (dim+2, DataComponentInterpretation::component_is_scalar); + stokes_component_interpretation + (dim+1, DataComponentInterpretation::component_is_scalar); for (unsigned int i=0; i::type_dof_data, - data_component_interpretation); + DataOut data_out; + data_out.add_data_vector (stokes_dof_handler, stokes_solution, + stokes_names, stokes_component_interpretation); + data_out.add_data_vector (temperature_dof_handler, temperature_solution, + "T"); data_out.build_patches (std::min(stokes_degree, temperature_degree)); std::ostringstream filename; diff --git a/deal.II/examples/step-32/CMakeLists.txt b/deal.II/examples/step-32/CMakeLists.txt index 4e68fdb217..7a72d94c82 100644 --- a/deal.II/examples/step-32/CMakeLists.txt +++ b/deal.II/examples/step-32/CMakeLists.txt @@ -11,9 +11,6 @@ SET(TARGET_SRC # You can specify additional files here! ) -# A custom command line to run the program -SET(TARGET_RUN mpirun -np 2 ${TARGET}) - # Define the output that should be cleaned: SET(CLEAN_UP_FILES *.vtu *.pvtu *.visit) @@ -43,7 +40,7 @@ Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_MPI = ON DEAL_II_WITH_P4EST = ON DEAL_II_WITH_TRILINOS = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-32/step-32.cc b/deal.II/examples/step-32/step-32.cc index 1b1d71ea0e..0c7ccc8a8f 100644 --- a/deal.II/examples/step-32/step-32.cc +++ b/deal.II/examples/step-32/step-32.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2008 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2008 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Martin Kronbichler, Uppsala University, * Wolfgang Bangerth, Texas A&M University, * Timo Heister, University of Goettingen, 2008-2011 @@ -3225,14 +3225,36 @@ namespace Step32 } - // The output_results() function does mostly what the - // corresponding one did in to step-31, in particular the merging data from - // the two DoFHandler objects (for the Stokes and the temperature parts of - // the problem) into one. There is one minor change: we make sure that each - // processor only works on the subdomain it owns locally (and not on ghost - // or artificial cells) when building the joint solution vector. The same - // will then have to be done in DataOut::build_patches(), but that function - // does so automatically. + // The output_results() function has a similar task to the one + // in step-31. However, here we are going to demonstrate a different + // technique on how to merge output from different DoFHandler objects. The + // way we're going to achieve this recombination is to create a joint + // DoFHandler that collects both components, the Stokes solution and the + // temperature solution. This can be nicely done by combining the finite + // elements from the two systems to form one FESystem, and let this + // collective system define a new DoFHandler object. To be sure that + // everything was done correctly, we perform a sanity check that ensures + // that we got all the dofs from both Stokes and temperature even in the + // combined system. We then combine the data vectors. Unfortunately, there + // is no straight-forward relation that tells us how to sort Stokes and + // temperature vector into the joint vector. The way we can get around this + // trouble is to rely on the information collected in the FESystem. For each + // dof on a cell, the joint finite element knows to which equation component + // (velocity component, pressure, or temperature) it belongs – that's the + // information we need! So we step through all cells (with iterators into + // all three DoFHandlers moving in synch), and for each joint cell dof, we + // read out that component using the FiniteElement::system_to_base_index + // function (see there for a description of what the various parts of its + // return value contain). We also need to keep track whether we're on a + // Stokes dof or a temperature dof, which is contained in + // joint_fe.system_to_base_index(i).first.first. Eventually, the dof_indices + // data structures on either of the three systems tell us how the relation + // between global vector and local dofs looks like on the present cell, + // which concludes this tedious work. We make sure that each processor only + // works on the subdomain it owns locally (and not on ghost or artificial + // cells) when building the joint solution vector. The same will then have + // to be done in DataOut::build_patches(), but that function does so + // automatically. // // What we end up with is a set of patches that we can write using the // functions in DataOutBase in a variety of output formats. Here, we then @@ -3306,7 +3328,8 @@ namespace Step32 } } } - + + joint_solution.compress(VectorOperation::insert); IndexSet locally_relevant_joint_dofs(joint_dof_handler.n_dofs()); DoFTools::extract_locally_relevant_dofs (joint_dof_handler, locally_relevant_joint_dofs); diff --git a/deal.II/examples/step-33/CMakeLists.txt b/deal.II/examples/step-33/CMakeLists.txt index 3264dbd6c8..308db41050 100644 --- a/deal.II/examples/step-33/CMakeLists.txt +++ b/deal.II/examples/step-33/CMakeLists.txt @@ -36,7 +36,7 @@ IF(NOT DEAL_II_WITH_TRILINOS) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_TRILINOS = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-33/step-33.cc b/deal.II/examples/step-33/step-33.cc index 3d17389c1b..de46484541 100644 --- a/deal.II/examples/step-33/step-33.cc +++ b/deal.II/examples/step-33/step-33.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2007 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2007 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: David Neckels, Boulder, Colorado, 2007, 2008 */ diff --git a/deal.II/examples/step-34/CMakeLists.txt b/deal.II/examples/step-34/CMakeLists.txt index 9f2b2ca256..b3b025bd9b 100644 --- a/deal.II/examples/step-34/CMakeLists.txt +++ b/deal.II/examples/step-34/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_FUNCTIONPARSER) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_FUNCTIONPARSER = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-34/step-34.cc b/deal.II/examples/step-34/step-34.cc index 9667a2dc9a..7eb237953a 100644 --- a/deal.II/examples/step-34/step-34.cc +++ b/deal.II/examples/step-34/step-34.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2009 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2009 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Luca Heltai, Cataldo Manigrasso, 2009 */ diff --git a/deal.II/examples/step-35/CMakeLists.txt b/deal.II/examples/step-35/CMakeLists.txt index 416238fcba..c35bddd9cf 100644 --- a/deal.II/examples/step-35/CMakeLists.txt +++ b/deal.II/examples/step-35/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_UMFPACK) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_UMFPACK = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-35/step-35.cc b/deal.II/examples/step-35/step-35.cc index 894966c8f5..6dfe49d2e7 100644 --- a/deal.II/examples/step-35/step-35.cc +++ b/deal.II/examples/step-35/step-35.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2009 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2009 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Abner Salgado, Texas A&M University 2009 */ @@ -1261,8 +1261,8 @@ namespace Step35 // pieces of data into a single DoFHandler object, and then use that to // drive graphical output. // - // We will not elaborate on this process here, but rather refer to step-31 - // and step-32, where a similar procedure is used (and is documented) to + // We will not elaborate on this process here, but rather refer to step-32, + // where a similar procedure is used (and is documented) to // create a joint DoFHandler object for all variables. // // Let us also note that we here compute the vorticity as a scalar quantity diff --git a/deal.II/examples/step-36/CMakeLists.txt b/deal.II/examples/step-36/CMakeLists.txt index 5e72c8ca3e..4d1eed8b19 100644 --- a/deal.II/examples/step-36/CMakeLists.txt +++ b/deal.II/examples/step-36/CMakeLists.txt @@ -34,7 +34,7 @@ IF(NOT DEAL_II_WITH_PETSC OR NOT DEAL_II_WITH_SLEPC) Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_PETSC = ON DEAL_II_WITH_SLEPC = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-36/doc/intro.dox b/deal.II/examples/step-36/doc/intro.dox index 69a89c4574..48d23ae0fd 100644 --- a/deal.II/examples/step-36/doc/intro.dox +++ b/deal.II/examples/step-36/doc/intro.dox @@ -72,7 +72,7 @@ eigenvalue. In order to numerically find solutions to this equation, i.e. a set of pairs of eigenvalues/eigenfunctions, we use the usual finite element -approach of multiplying the equation from the left with testfunctions, +approach of multiplying the equation from the left with test functions, integrating by parts, and searching for solutions in finite dimensional spaces by approximating $\Psi(\mathbf x)\approx\Psi_h(\mathbf x)=\sum_{j}\phi_j(\mathbf x)\tilde\psi_j$, diff --git a/deal.II/examples/step-36/step-36.cc b/deal.II/examples/step-36/step-36.cc index 7c93a435c4..13869b83ef 100644 --- a/deal.II/examples/step-36/step-36.cc +++ b/deal.II/examples/step-36/step-36.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2009 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2009 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Toby D. Young, Polish Academy of Sciences, * Wolfgang Bangerth, Texas A&M University */ diff --git a/deal.II/examples/step-37/CMakeLists.txt b/deal.II/examples/step-37/CMakeLists.txt index 4b4e8f3f32..07a25bc701 100644 --- a/deal.II/examples/step-37/CMakeLists.txt +++ b/deal.II/examples/step-37/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_LAPACK) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_LAPACK = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-37/step-37.cc b/deal.II/examples/step-37/step-37.cc index 62c51b30ac..8a2a17723d 100644 --- a/deal.II/examples/step-37/step-37.cc +++ b/deal.II/examples/step-37/step-37.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2009 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2009 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Katharina Kormann, Martin Kronbichler, Uppsala University, 2009-2012 */ diff --git a/deal.II/examples/step-38/step-38.cc b/deal.II/examples/step-38/step-38.cc index d1bcf3bc98..d8d17da2b2 100644 --- a/deal.II/examples/step-38/step-38.cc +++ b/deal.II/examples/step-38/step-38.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2010 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2010 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Andrea Bonito, Sebastian Pauletti. */ diff --git a/deal.II/examples/step-39/step-39.cc b/deal.II/examples/step-39/step-39.cc index 1067a95822..61f2eba90e 100644 --- a/deal.II/examples/step-39/step-39.cc +++ b/deal.II/examples/step-39/step-39.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2010 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2010 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Guido Kanschat, Texas A&M University, 2009 */ diff --git a/deal.II/examples/step-4/step-4.cc b/deal.II/examples/step-4/step-4.cc index 8dc0d0a529..d8e92fa132 100644 --- a/deal.II/examples/step-4/step-4.cc +++ b/deal.II/examples/step-4/step-4.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 1999 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 1999 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 1999 */ diff --git a/deal.II/examples/step-40/CMakeLists.txt b/deal.II/examples/step-40/CMakeLists.txt index ed9f3e4c1d..f024774a4e 100644 --- a/deal.II/examples/step-40/CMakeLists.txt +++ b/deal.II/examples/step-40/CMakeLists.txt @@ -34,7 +34,7 @@ IF(NOT DEAL_II_WITH_PETSC OR NOT DEAL_II_WITH_P4EST) Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_PETSC = ON DEAL_II_WITH_P4EST = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-40/step-40.cc b/deal.II/examples/step-40/step-40.cc index d50694e9f9..979f6b060b 100644 --- a/deal.II/examples/step-40/step-40.cc +++ b/deal.II/examples/step-40/step-40.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2009 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2009 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, Texas A&M University, 2009, 2010 * Timo Heister, University of Goettingen, 2009, 2010 */ diff --git a/deal.II/examples/step-41/CMakeLists.txt b/deal.II/examples/step-41/CMakeLists.txt index c4e08a8cf3..1ecef89b0a 100644 --- a/deal.II/examples/step-41/CMakeLists.txt +++ b/deal.II/examples/step-41/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_TRILINOS) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_TRILINOS = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-41/step-41.cc b/deal.II/examples/step-41/step-41.cc index 80ac9f3305..b177c92a20 100644 --- a/deal.II/examples/step-41/step-41.cc +++ b/deal.II/examples/step-41/step-41.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2011 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2011 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Joerg Frohne, Texas A&M University and * University of Siegen, 2011, 2012 * Wolfgang Bangerth, Texas A&M University, 2012 diff --git a/deal.II/examples/step-42/CMakeLists.txt b/deal.II/examples/step-42/CMakeLists.txt index dc468213e4..78a6df2f1f 100644 --- a/deal.II/examples/step-42/CMakeLists.txt +++ b/deal.II/examples/step-42/CMakeLists.txt @@ -11,9 +11,6 @@ SET(TARGET_SRC # You can specify additional files here! ) -# A custom command line to run the program -SET(TARGET_RUN mpirun -np 2 ${TARGET}) - # Define the output that should be cleaned: SET(CLEAN_UP_FILES *.vtu *.pvtu *.visit) @@ -43,7 +40,7 @@ Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_MPI = ON DEAL_II_WITH_P4EST = ON DEAL_II_WITH_TRILINOS = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-42/doc/intro-step-42.tex b/deal.II/examples/step-42/doc/intro-step-42.tex index a6c6b1f752..7f2e577d33 100644 --- a/deal.II/examples/step-42/doc/intro-step-42.tex +++ b/deal.II/examples/step-42/doc/intro-step-42.tex @@ -83,7 +83,7 @@ is zero with the outward normal $n$. If there is contact ($u_n = g$) the tangent vanishes, because we consider a frictionless situation and the normal stress is negative. The gap $g$ comes with the start configuration of the obstacle and the deformable body. We refer that you have to ensure that the obstacle does not hit -the boundary of $\Gamma_C$ +the boundary of $\Gamma_C$ \section{Derivation of the variational inequality} @@ -227,7 +227,8 @@ Again the first case is for elastic and the second for plastic deformation. Just as in step-41 we compose a saddle point problem out of the minimisation problem. Again we do so to gain a formulation that allows us to solve a linear -system of equations finally.\\ +system of equations finally. + We introduce a Lagrange multiplier $\lambda$ and the convex cone $K\subset W'$, $W'$ dual space of the trace space $W:=\left[ H_0^{\frac{1}{2}}(\Gamma_C) \right]^{\textrm{dim}}$ of $V$ restricted to $\Gamma_C$, $$K:=\{\mu\in W':\mu_T = 0,\quad\langle\mu n,v\rangle_{\Gamma_C}\geq 0,\quad @@ -236,9 +237,8 @@ of Lagrange multipliers, where $\langle\cdot,\cdot\rangle$ denotes the duality pairing, i.e. a boundary integral, between $W'$ and $W$. Intuitively, $K$ is the cone of all "non-positive functions", except that $ K\subset \left( \left[ H_0^{\frac{1}{2}}(\Gamma_C) \right]^{\textrm{dim}} \right)' $ and -so contains other objects besides regular functions as well. This yields:\\ +so contains other objects besides regular functions as well. This yields: -\noindent \textit{Find $u\in V$ and $\lambda\in K$ such that} \begin{align*} \hat{a}(u,v) + b(v,\lambda) &= f(v),\quad &&v\in V\\ @@ -304,7 +304,7 @@ method for the contact. It sums up the results of the sections before and works $$\mathcal{F}_{k+1}:=\lbrace p\in\mathcal{S}:\Lambda^k_p + c\left(\left[B^TU^k\right]_p - G_p\right) \leq 0\rbrace.$$ Projection $U^k$ so that it holds the second equation in (2) - $$\hat U^K := P_{\mathcal{A}_{k+1}}(U^k).$$ + $$\hat U^K := P_{\mathcal{A}_{k+1}}(U^k).$$ \item[(5)] If $\mathcal{A}_{k+1} = \mathcal{A}_k$ and $\vert F\left(U^{k}\right) \vert < \delta$ then stop, else set $k=k+1$ and go to step (1). @@ -353,7 +353,7 @@ above that we only linearize the problem. In step (2) we have to solve a linear criteria. $\mathcal{A}_{k+1} = \mathcal{A}_k$ makes sure that the contact zones are iterated out and the second ensures an accurate enough residual which means that the plastic zones are also iterated out.\\ A similar method can also be found in Brunssen, Schmid, Schaefer, Wohlmuth: A -fast and robust iterative solver for nonlinear contact problems using a +fast and robust iterative solver for nonlinear contact problems using a primal-dual active set strategy and algebraic multigrid, Int. J. Numer. Meth. Engng, 2007, 69, pp. 524-543. But in advance we apply a line search to obtain a more robust method regarding the start value. Solving an elastic @@ -379,12 +379,12 @@ results it yields a quite reasonable adaptive mesh for the contact zone. This tutorial is essentailly a mixture of step-40 and step-41 but instead of PETSc we let the Trilinos library deal with parallelizing the linear algebra -(like in step-32). Since we are trying to solve a similar problem like in +(like in step-32). Since we are trying to solve a similar problem like in step-41 we will use the same methods but now in parallel. Another difficulty is the handling of the different constraints from -(the dirichlet conditons), the hanging nodes and the inequality condition that -arises from the contact. For this purpose we create three objects of type +(the dirichlet conditons), the hanging nodes and the inequality condition that +arises from the contact. For this purpose we create three objects of type ConstraintMatrix. Beside the ConstitutiveLaw class there is another new class called Input. This diff --git a/deal.II/examples/step-42/p1_adaptive.prm b/deal.II/examples/step-42/p1_adaptive.prm new file mode 100644 index 0000000000..dd5f63c008 --- /dev/null +++ b/deal.II/examples/step-42/p1_adaptive.prm @@ -0,0 +1,25 @@ +# Listing of Parameters +# --------------------- + +# polynomial degree of the FE_Q finite element space, typically 1 or 2 +set polynomial degree = 1 + +# number of initial global refinements before the first computation +set number of initial refinements = 3 + +# number of adaptive cycles to run +set number of cycles = 12 + +# refinement strategy for each cycle: +# global: one global refinement +# percentage: fixed percentage gets refined using kelly +# fix dofs: tries to achieve 2^initial_refinement*300 dofs after cycle 1 (only +# use 2 cycles!). Changes the coarse mesh! +set refinement strategy = percentage + +# obstacle file to read, leave empty to use a sphere or 'obstacle_file.pbm' +set obstacle filename = + +# directory to put output files (graphical output and benchmark statistics, +# leave empty to put into current directory +set output directory = p1adaptive diff --git a/deal.II/examples/step-42/p1_global.prm b/deal.II/examples/step-42/p1_global.prm new file mode 100644 index 0000000000..ead72fb52e --- /dev/null +++ b/deal.II/examples/step-42/p1_global.prm @@ -0,0 +1,25 @@ +# Listing of Parameters +# --------------------- + +# polynomial degree of the FE_Q finite element space, typically 1 or 2 +set polynomial degree = 1 + +# number of initial global refinements before the first computation +set number of initial refinements = 3 + +# number of adaptive cycles to run +set number of cycles = 7 + +# refinement strategy for each cycle: +# global: one global refinement +# percentage: fixed percentage gets refined using kelly +# fix dofs: tries to achieve 2^initial_refinement*300 dofs after cycle 1 (only +# use 2 cycles!). Changes the coarse mesh! +set refinement strategy = global + +# obstacle file to read, leave empty to use a sphere or 'obstacle_file.pbm' +set obstacle filename = + +# directory to put output files (graphical output and benchmark statistics, +# leave empty to put into current directory +set output directory = p1global diff --git a/deal.II/examples/step-42/p2_adaptive.prm b/deal.II/examples/step-42/p2_adaptive.prm new file mode 100644 index 0000000000..3c06265efd --- /dev/null +++ b/deal.II/examples/step-42/p2_adaptive.prm @@ -0,0 +1,25 @@ +# Listing of Parameters +# --------------------- + +# polynomial degree of the FE_Q finite element space, typically 1 or 2 +set polynomial degree = 2 + +# number of initial global refinements before the first computation +set number of initial refinements = 2 + +# number of adaptive cycles to run +set number of cycles = 11 + +# refinement strategy for each cycle: +# global: one global refinement +# percentage: fixed percentage gets refined using kelly +# fix dofs: tries to achieve 2^initial_refinement*300 dofs after cycle 1 (only +# use 2 cycles!). Changes the coarse mesh! +set refinement strategy = percentage + +# obstacle file to read, leave empty to use a sphere or 'obstacle_file.pbm' +set obstacle filename = + +# directory to put output files (graphical output and benchmark statistics, +# leave empty to put into current directory +set output directory = p2adaptive diff --git a/deal.II/examples/step-42/p2_global.prm b/deal.II/examples/step-42/p2_global.prm new file mode 100644 index 0000000000..f721e417e3 --- /dev/null +++ b/deal.II/examples/step-42/p2_global.prm @@ -0,0 +1,25 @@ +# Listing of Parameters +# --------------------- + +# polynomial degree of the FE_Q finite element space, typically 1 or 2 +set polynomial degree = 2 + +# number of initial global refinements before the first computation +set number of initial refinements = 3 + +# number of adaptive cycles to run +set number of cycles = 6 + +# refinement strategy for each cycle: +# global: one global refinement +# percentage: fixed percentage gets refined using kelly +# fix dofs: tries to achieve 2^initial_refinement*300 dofs after cycle 1 (only +# use 2 cycles!). Changes the coarse mesh! +set refinement strategy = global + +# obstacle file to read, leave empty to use a sphere or 'obstacle_file.pbm' +set obstacle filename = + +# directory to put output files (graphical output and benchmark statistics, +# leave empty to put into current directory +set output directory = p2global diff --git a/deal.II/examples/step-42/step-42.cc b/deal.II/examples/step-42/step-42.cc index 0ac5426c5c..efcdad4921 100644 --- a/deal.II/examples/step-42/step-42.cc +++ b/deal.II/examples/step-42/step-42.cc @@ -1,34 +1,37 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 1999 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* - * Author: Wolfgang Bangerth, University of Heidelberg, 1999 +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2012 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * + * Authors: Joerg Frohne, Texas A&M University and + * University of Siegen, 2012, 2013 + * Wolfgang Bangerth, Texas A&M University, 2012, 2013 + * Timo Heister, Texas A&M University, 2013 */ // @sect3{Include files} - // We are using the the same // include files as in step-41: - #include #include #include +#include #include #include +#include #include #include #include @@ -44,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -57,6 +59,7 @@ #include #include +#include #include #include #include @@ -65,6 +68,7 @@ #include #include +#include #include #include #include @@ -72,1571 +76,1987 @@ #include #include +#include #include -namespace Step42 -{ - using namespace dealii; - - // @sect3{The Input class template} - - // This class has the the only purpose - // to read in data from a picture file - // that has to be stored in pbm ascii - // format. This data will be bilinear - // interpolated and provides in this way - // a function which describes an obstacle. - // - // The data which we read in by the - // function read_obstacle () from the file - // "obstacle_file.pbm" will be stored - // in a double std::vector named - // obstacle_data. - // This vector composes the base - // to calculate a piecewise bilinear - // function as a polynomial interpolation. - // This will be done by obstacle_function (). - // - // In the function run () of the class - // PlasticityContactProblem we create - // an object of the class Input which will - // be used in the class Obstacle to - // supply the obstacle function in - // update_solution_and_constraints () of - // the class PlasticityContactProblem. - - template - class Input - { - public: - Input (const char *_name) : - name (_name), - mpi_communicator (MPI_COMM_WORLD), - pcout (std::cout, - (Utilities::MPI::this_mpi_process(mpi_communicator) == 0)), - obstacle_data (0), - hx (0), - hy (0), - nx (0), - ny (0) - { - read_obstacle (name); - } +namespace Step42 { +using namespace dealii; - double hv (int i, int j); +// @sect3{The Input class template} - double obstacle_function (double x,double y); +// This class has the the only purpose +// to read in data from a picture file +// that has to be stored in pbm ascii +// format. This data will be bilinear +// interpolated and provides in this way +// a function which describes an obstacle. +// +// The data which we read in by the +// function read_obstacle () from the file +// "obstacle_file.pbm" will be stored +// in a double std::vector named +// obstacle_data. +// This vector composes the base +// to calculate a piecewise bilinear +// function as a polynomial interpolation. +// This will be done by obstacle_function (). +// +// In the function run () of the class +// PlasticityContactProblem we create +// an object of the class Input which will +// be used in the class Obstacle to +// supply the obstacle function in +// update_solution_and_constraints () of +// the class PlasticityContactProblem. + +template +class Input { +public: + Input(const char* _name) : + name(_name), mpi_communicator(MPI_COMM_WORLD), pcout(std::cout, + (Utilities::MPI::this_mpi_process(mpi_communicator) == 0)), obstacle_data( + 0), hx(0), hy(0), nx(0), ny(0) { + read_obstacle(name); + } + + double + hv(int i, int j); + + double + obstacle_function(double x, double y); + + void + read_obstacle(const char* name); + +private: + const char* name; + MPI_Comm mpi_communicator; + ConditionalOStream pcout; + std::vector obstacle_data; + double hx, hy; + int nx, ny; +}; + +// This function is used in obstacle_function () +// to provide the proper value of the obstacle. +template +double Input::hv(int i, int j) { + assert(i >= 0 && i < nx); + assert(j >= 0 && j < ny); + return obstacle_data[nx * (ny - 1 - j) + i]; // i indiziert x-werte, j indiziert y-werte +} - void read_obstacle (const char *name); +// obstacle_function () calculates the bilinear interpolated +// value in the point (x,y). +template +double Input::obstacle_function(double x, double y) { + int ix = (int) (x / hx); + int iy = (int) (y / hy); + + if (ix < 0) + ix = 0; + + if (iy < 0) + iy = 0; + + if (ix >= nx - 1) + ix = nx - 2; + + if (iy >= ny - 1) + iy = ny - 2; + + double val = 0.0; + { + FullMatrix H(4, 4); + Vector X(4); + Vector b(4); + + double xx = 0.0; + double yy = 0.0; + + xx = ix * hx; + yy = iy * hy; + H(0, 0) = xx; + H(0, 1) = yy; + H(0, 2) = xx * yy; + H(0, 3) = 1.0; + b(0) = hv(ix, iy); + + xx = (ix + 1) * hx; + yy = iy * hy; + H(1, 0) = xx; + H(1, 1) = yy; + H(1, 2) = xx * yy; + H(1, 3) = 1.0; + b(1) = hv(ix + 1, iy); + + xx = (ix + 1) * hx; + yy = (iy + 1) * hy; + H(2, 0) = xx; + H(2, 1) = yy; + H(2, 2) = xx * yy; + H(2, 3) = 1.0; + b(2) = hv(ix + 1, iy + 1); + + xx = ix * hx; + yy = (iy + 1) * hy; + H(3, 0) = xx; + H(3, 1) = yy; + H(3, 2) = xx * yy; + H(3, 3) = 1.0; + b(3) = hv(ix, iy + 1); + + H.gauss_jordan(); + H.vmult(X, b); + + val = X(0) * x + X(1) * y + X(2) * x * y + X(3); + } + + return val; +} - private: - const char *name; - MPI_Comm mpi_communicator; - ConditionalOStream pcout; - std::vector obstacle_data; - double hx, hy; - int nx, ny; - }; +// As mentioned above this function reads in the +// obstacle datas and stores them in the std::vector +// obstacle_data. It will be used only in run (). +template +void Input::read_obstacle(const char* name) { + std::ifstream f(name); - // This function is used in obstacle_function () - // to provide the proper value of the obstacle. - template - double Input::hv (int i, int j) - { - assert(i>=0 && i=0 && j> temp >> nx >> ny; + assert(nx > 0 && ny > 0); - // obstacle_function () calculates the bilinear interpolated - // value in the point (x,y). - template - double Input::obstacle_function (double x,double y) - { - int ix = (int)(x/hx); - int iy = (int)(y/hy); + for (int k = 0; k < nx * ny; k++) { + double val; + f >> val; + obstacle_data.push_back(val); + } - if (ix<0) - ix = 0; + hx = 1.0 / (nx - 1); + hy = 1.0 / (ny - 1); - if (iy<0) - iy = 0; + pcout << "Resolution of the scanned obstacle picture: " << nx << " x " << ny + << std::endl; +} - if (ix>=nx-1) - ix = nx-2; +// @sect3{The ConstitutiveLaw class template} + +// This class provides an interface +// for a constitutive law. In this +// example we are using an elasto +// plastic material behavior with linear, +// isotropic hardening. +// For gamma = 0 we obtain perfect elasto +// plasticity behavior. +template +class ConstitutiveLaw { +public: + ConstitutiveLaw(double _E, double _nu, double _sigma_0, double _gamma, + MPI_Comm _mpi_communicator, ConditionalOStream _pcout); + + void + plast_linear_hardening(SymmetricTensor<4, dim> &stress_strain_tensor, + const SymmetricTensor<2, dim> &strain_tensor, + unsigned int &elast_points, unsigned int &plast_points, + double &yield); + void + linearized_plast_linear_hardening( + SymmetricTensor<4, dim> &stress_strain_tensor_linearized, + SymmetricTensor<4, dim> &stress_strain_tensor, + const SymmetricTensor<2, dim> &strain_tensor); + inline SymmetricTensor<2, dim> + get_strain(const FEValues &fe_values, const unsigned int shape_func, + const unsigned int q_point) const; + void set_sigma_0(double sigma_hlp) { + sigma_0 = sigma_hlp; + } + +private: + SymmetricTensor<4, dim> stress_strain_tensor_mu; + SymmetricTensor<4, dim> stress_strain_tensor_kappa; + double E; + double nu; + double sigma_0; + double gamma; + double mu; + double kappa; + MPI_Comm mpi_communicator; + ConditionalOStream pcout; +}; + +// The constructor of the ConstitutiveLaw class sets the +// required material parameter for our deformable body: +// E -> elastic modulus +// nu -> Passion's number +// sigma_0 -> yield stress +// gamma -> hardening parameter. +// Also it supplies the stress strain tensor of forth order +// of the volumetric and deviator part. For further details +// see the documentation above. +template +ConstitutiveLaw::ConstitutiveLaw(double _E, double _nu, double _sigma_0, + double _gamma, MPI_Comm _mpi_communicator, ConditionalOStream _pcout) : + E(_E), nu(_nu), sigma_0(_sigma_0), gamma(_gamma), mpi_communicator( + _mpi_communicator), pcout(_pcout) { + mu = E / (2 * (1 + nu)); + kappa = E / (3 * (1 - 2 * nu)); + stress_strain_tensor_kappa = kappa + * outer_product(unit_symmetric_tensor(), + unit_symmetric_tensor()); + stress_strain_tensor_mu = 2 * mu + * (identity_tensor() + - outer_product(unit_symmetric_tensor(), + unit_symmetric_tensor()) / 3.0); +} - if (iy>=ny-1) - iy = ny-2; +// @sect3{ConstitutiveLaw::ConstitutiveLaw} - double val = 0.0; - { - FullMatrix H(4,4); - Vector X(4); - Vector b(4); - - double xx = 0.0; - double yy = 0.0; - - xx = ix*hx; - yy = iy*hy; - H(0,0) = xx; - H(0,1) = yy; - H(0,2) = xx*yy; - H(0,3) = 1.0; - b(0) = hv (ix, iy); - - xx = (ix + 1)*hx; - yy = iy*hy; - H(1,0) = xx; - H(1,1) = yy; - H(1,2) = xx*yy; - H(1,3) = 1.0; - b(1) = hv (ix + 1, iy); - - xx = (ix + 1)*hx; - yy = (iy + 1)*hy; - H(2,0) = xx; - H(2,1) = yy; - H(2,2) = xx*yy; - H(2,3) = 1.0; - b(2) = hv (ix + 1, iy + 1); - - xx = ix*hx; - yy = (iy + 1)*hy; - H(3,0) = xx; - H(3,1) = yy; - H(3,2) = xx*yy; - H(3,3) = 1.0; - b(3) = hv (ix, iy + 1); - - H.gauss_jordan (); - H.vmult (X, b); - - val = X(0)*x + X(1)*y + X(2)*x*y + X(3); - } +// Calculates the strain for the shape functions. +template +inline SymmetricTensor<2, dim> ConstitutiveLaw::get_strain( + const FEValues &fe_values, const unsigned int shape_func, + const unsigned int q_point) const { + const FEValuesExtractors::Vector displacement(0); + SymmetricTensor < 2, dim > tmp; - return val; - } + tmp = fe_values[displacement].symmetric_gradient(shape_func, q_point); - // As mentioned above this function reads in the - // obstacle datas and stores them in the std::vector - // obstacle_data. It will be used only in run (). - template - void Input::read_obstacle (const char *name) - { - std::ifstream f(name); + return tmp; +} - std::string temp; - f >> temp >> nx >> ny; - assert(nx>0 && ny>0); +// @sect3{ConstitutiveLaw::plast_linear_hardening} + +// This is the implemented constitutive law. It projects the +// deviator part of the stresses in a quadrature point back to +// the yield stress plus the linear isotropic hardening. +// Also we sum up the elastic and the plastic quadrature +// points. +template +void ConstitutiveLaw::plast_linear_hardening( + SymmetricTensor<4, dim> &stress_strain_tensor, + const SymmetricTensor<2, dim> &strain_tensor, + unsigned int &elast_points, unsigned int &plast_points, double &yield) { + if (dim == 3) { + SymmetricTensor < 2, dim > stress_tensor; + stress_tensor = (stress_strain_tensor_kappa + stress_strain_tensor_mu) + * strain_tensor; + + SymmetricTensor < 2, dim > deviator_stress_tensor = deviator( + stress_tensor); + + double deviator_stress_tensor_norm = deviator_stress_tensor.norm(); + + yield = 0; + stress_strain_tensor = stress_strain_tensor_mu; + double beta = 1.0; + if (deviator_stress_tensor_norm > sigma_0) { + beta = sigma_0 / deviator_stress_tensor_norm; + stress_strain_tensor *= (gamma + (1 - gamma) * beta); + yield = 1; + plast_points += 1; + } else + elast_points += 1; + + stress_strain_tensor += stress_strain_tensor_kappa; + } +} - for (int k=0; k> val; - obstacle_data.push_back(val); - } +// @sect3{ConstitutiveLaw::linearized_plast_linear_hardening} + +// This function returns the linearized stress strain tensor. +// It contains the derivative of the nonlinear constitutive law. +template +void ConstitutiveLaw::linearized_plast_linear_hardening( + SymmetricTensor<4, dim> &stress_strain_tensor_linearized, + SymmetricTensor<4, dim> &stress_strain_tensor, + const SymmetricTensor<2, dim> &strain_tensor) { + if (dim == 3) { + SymmetricTensor < 2, dim > stress_tensor; + stress_tensor = (stress_strain_tensor_kappa + stress_strain_tensor_mu) + * strain_tensor; + + SymmetricTensor < 2, dim > deviator_stress_tensor = deviator( + stress_tensor); + + double deviator_stress_tensor_norm = deviator_stress_tensor.norm(); + + stress_strain_tensor = stress_strain_tensor_mu; + stress_strain_tensor_linearized = stress_strain_tensor_mu; + double beta = 1.0; + if (deviator_stress_tensor_norm > sigma_0) { + beta = sigma_0 / deviator_stress_tensor_norm; + stress_strain_tensor *= (gamma + (1 - gamma) * beta); + stress_strain_tensor_linearized *= (gamma + (1 - gamma) * beta); + deviator_stress_tensor /= deviator_stress_tensor_norm; + stress_strain_tensor_linearized -= (1 - gamma) * beta * 2 * mu + * outer_product(deviator_stress_tensor, + deviator_stress_tensor); + } + + stress_strain_tensor += stress_strain_tensor_kappa; + stress_strain_tensor_linearized += stress_strain_tensor_kappa; + } +} - hx = 1.0/(nx - 1); - hy = 1.0/(ny - 1); +namespace EquationData { +// It possible to apply an additional body force +// but in here it is set to zero. +template +class RightHandSide: public Function { +public: + RightHandSide() : + Function(dim) { + } + + virtual double + value(const Point &p, const unsigned int component = 0) const; + + virtual void + vector_value(const Point &p, Vector &values) const; +}; + +template +double RightHandSide::value(const Point &p, + const unsigned int component) const { + double return_value = 0.0; + + if (component == 0) + return_value = 0.0; + if (component == 1) + return_value = 0.0; + if (component == 2) + return_value = 0.0;//-26923.07692; + + return return_value; +} - pcout << "Resolution of the scanned obstacle picture: " << nx << " x " << ny << std::endl; - } +template +void RightHandSide::vector_value(const Point &p, + Vector &values) const { + for (unsigned int c = 0; c < this->n_components; ++c) + values(c) = RightHandSide::value(p, c); +} - // @sect3{The ConstitutiveLaw class template} - - // This class provides an interface - // for a constitutive law. In this - // example we are using an elasto - // plastic material behavior with linear, - // isotropic hardening. - // For gamma = 0 we obtain perfect elasto - // plasticity behavior. - template - class ConstitutiveLaw - { - public: - ConstitutiveLaw (double _E, - double _nu, - double _sigma_0, - double _gamma, - MPI_Comm _mpi_communicator, - ConditionalOStream _pcout); - - void plast_linear_hardening (SymmetricTensor<4,dim> &stress_strain_tensor, - const SymmetricTensor<2,dim> &strain_tensor, - unsigned int &elast_points, - unsigned int &plast_points, - double &yield); - void linearized_plast_linear_hardening (SymmetricTensor<4,dim> &stress_strain_tensor_linearized, - SymmetricTensor<4,dim> &stress_strain_tensor, - const SymmetricTensor<2,dim> &strain_tensor); - inline SymmetricTensor<2,dim> get_strain (const FEValues &fe_values, - const unsigned int shape_func, - const unsigned int q_point) const; - void set_sigma_0 (double sigma_hlp) - { - sigma_0 = sigma_hlp; - } +// This function class is used to describe the prescribed displacements +// at the boundary. But again we set this to zero. +template +class BoundaryValues: public Function { +public: + BoundaryValues() : + Function(dim) { + } + ; + + virtual double + value(const Point &p, const unsigned int component = 0) const; + + virtual void + vector_value(const Point &p, Vector &values) const; +}; + +template +double BoundaryValues::value(const Point &p, + const unsigned int component) const { + double return_value = 0; + + if (component == 0) + return_value = 0.0; + if (component == 1) + return_value = 0.0; + if (component == 2) + return_value = 0.0; + + return return_value; +} - private: - SymmetricTensor<4,dim> stress_strain_tensor_mu; - SymmetricTensor<4,dim> stress_strain_tensor_kappa; - double E; - double nu; - double sigma_0; - double gamma; - double mu; - double kappa; - MPI_Comm mpi_communicator; - ConditionalOStream pcout; - }; - - // The constructor of the ConstitutiveLaw class sets the - // required material parameter for our deformable body: - // E -> elastic modulus - // nu -> Passion's number - // sigma_0 -> yield stress - // gamma -> hardening parameter. - // Also it supplies the stress strain tensor of forth order - // of the volumetric and deviator part. For further details - // see the documentation above. - template - ConstitutiveLaw::ConstitutiveLaw(double _E, double _nu, double _sigma_0, double _gamma, MPI_Comm _mpi_communicator, ConditionalOStream _pcout) - :E (_E), - nu (_nu), - sigma_0 (_sigma_0), - gamma (_gamma), - mpi_communicator (_mpi_communicator), - pcout (_pcout) - { - mu = E/(2*(1+nu)); - kappa = E/(3*(1-2*nu)); - stress_strain_tensor_kappa = kappa*outer_product(unit_symmetric_tensor(), unit_symmetric_tensor()); - stress_strain_tensor_mu = 2*mu*(identity_tensor() - outer_product(unit_symmetric_tensor(), unit_symmetric_tensor())/3.0); - } +template +void BoundaryValues::vector_value(const Point &p, + Vector &values) const { + for (unsigned int c = 0; c < this->n_components; ++c) + values(c) = BoundaryValues::value(p, c); +} - // Calculates the strain for the shape functions. - template - inline - SymmetricTensor<2,dim> ConstitutiveLaw::get_strain (const FEValues &fe_values, - const unsigned int shape_func, - const unsigned int q_point) const - { - const FEValuesExtractors::Vector displacement (0); - SymmetricTensor<2,dim> tmp; +// This function is obviously implemented to +// define the obstacle that penetrates our deformable +// body. You can choose between two ways to define +// your obstacle: to read it from a file or to use +// a function (here a ball). +// z_max_domain is the z value of the surface of the work piece +template +class Obstacle: public Function { +public: + Obstacle(std_cxx1x::shared_ptr > const &_input, + bool _use_read_obstacle, double z_max_domain) : + Function(dim), input_obstacle_copy(_input), use_read_obstacle( + _use_read_obstacle), + z_max_domain(z_max_domain){ + } + + virtual double + value(const Point &p, const unsigned int component = 0) const; + + virtual void + vector_value(const Point &p, Vector &values) const; + +private: + std_cxx1x::shared_ptr > const &input_obstacle_copy; + bool use_read_obstacle; + double z_max_domain; +}; + +template +double Obstacle::value(const Point &p, + const unsigned int component) const { + if (component == 0) + return p(0); + if (component == 1) + return p(1); + + //component==2: + if (use_read_obstacle) + { + if (p(0) >= 0.0 && p(0) <= 1.0 && p(1) >= 0.0 && p(1) <= 1.0) + return z_max_domain + 0.999 - input_obstacle_copy->obstacle_function(p(0), p(1)); + else + return 10000.0; + } + else + { + //sphere: + return -std::sqrt( + 0.36 - (p(0) - 0.5) * (p(0) - 0.5) + - (p(1) - 0.5) * (p(1) - 0.5)) + z_max_domain + 0.59; + } +} - tmp = fe_values[displacement].symmetric_gradient (shape_func,q_point); +template +void Obstacle::vector_value(const Point &p, + Vector &values) const { + for (unsigned int c = 0; c < this->n_components; ++c) + values(c) = Obstacle::value(p, c); +} +} - return tmp; - } +// @sect3{The PlasticityContactProblem class template} + +// This class supplies all function +// and variables needed to describe +// the nonlinear contact problem. It is +// close to step-41 but with some additional +// features like: handling hanging nodes, +// a newton method, using Trilinos and p4est +// for parallel distributed computing. +// To deal with hanging nodes makes +// life a bit more complicated since +// we need an other ConstraintMatrix now. +// We create a newton method for the +// active set method for the contact +// situation and to handle the nonlinear +// operator for the constitutive law. + +template +class PlasticityContactProblem { +public: + PlasticityContactProblem(const ParameterHandler &prm); + void + run(); + + static void + declare(ParameterHandler &prm); + +private: + void + make_grid(); + void + setup_system(); + void + assemble_nl_system(TrilinosWrappers::MPI::Vector &u); + void + residual_nl_system(TrilinosWrappers::MPI::Vector &u); + void + assemble_mass_matrix_diagonal(TrilinosWrappers::SparseMatrix &mass_matrix); + void + update_solution_and_constraints(); + void + dirichlet_constraints(); + void + solve(); + void + solve_newton(); + void + refine_grid(); + void + move_mesh( + const TrilinosWrappers::MPI::Vector &_complete_displacement) const; + void + output_results(const std::string &title); + void + output_for_benchmark(const unsigned int cycle); + + double to_refine_factor; + double to_coarsen_factor; + unsigned int cycle; + + MPI_Comm mpi_communicator; + + parallel::distributed::Triangulation triangulation; + + FE_Q u; + FESystem fe; + DoFHandler dof_handler; + + std_cxx1x::shared_ptr< + parallel::distributed::SolutionTransfer > soltrans; + + IndexSet locally_owned_dofs; + IndexSet locally_relevant_dofs; + + unsigned int number_iterations; + + ConstraintMatrix constraints; + ConstraintMatrix constraints_hanging_nodes; + ConstraintMatrix constraints_dirichlet_hanging_nodes; + + TrilinosWrappers::SparseMatrix system_matrix_newton; + + TrilinosWrappers::MPI::Vector solution; + TrilinosWrappers::MPI::Vector system_rhs_newton; + TrilinosWrappers::MPI::Vector system_rhs_lambda; + TrilinosWrappers::MPI::Vector resid_vector; + TrilinosWrappers::MPI::Vector diag_mass_matrix_vector; + Vector cell_constitution; + IndexSet active_set; + + ConditionalOStream pcout; + + TrilinosWrappers::PreconditionAMG::AdditionalData additional_data; + TrilinosWrappers::PreconditionAMG preconditioner_u; + + std_cxx1x::shared_ptr > input_obstacle; + std_cxx1x::shared_ptr > plast_lin_hard; + + double sigma_0; // Yield stress + double gamma; // Parameter for the linear isotropic hardening + double e_modul; // E-Modul + double nu; // Poisson ratio + + TimerOutput computing_timer; + + unsigned int degree; + unsigned int n_initial_refinements; + struct RefinementStrategy + { + enum value + { + refine_global, + refine_percentage, + refine_fix_dofs + }; + }; + typename RefinementStrategy::value refinement_strategy; + unsigned int n_cycles; + std::string obstacle_filename; + std::string output_dir; + bool transfer_solution; + std::string base_mesh; +}; + +// @sect3{Implementation of the PlasticityContactProblem class} + +// Next for the implementation of the class +// template that makes use of the functions +// above. As before, we will write everything + +template +PlasticityContactProblem::PlasticityContactProblem( + const ParameterHandler &prm) : + mpi_communicator(MPI_COMM_WORLD), triangulation(mpi_communicator), + u(QGaussLobatto< 1 > (prm.get_integer("polynomial degree")+1)), + fe(u, dim), + dof_handler(triangulation), pcout( + std::cout, + (Utilities::MPI::this_mpi_process(mpi_communicator) == 0)), sigma_0( + 400.0), gamma(0.01), e_modul(2.0e+5), nu(0.3), computing_timer( + MPI_COMM_WORLD, pcout, TimerOutput::never, + TimerOutput::wall_times) { + // double _E, double _nu, double _sigma_0, double _gamma + plast_lin_hard.reset( + new ConstitutiveLaw(e_modul, nu, sigma_0, gamma, + mpi_communicator, pcout)); + + degree = prm.get_integer("polynomial degree"); + n_initial_refinements = prm.get_integer("number of initial refinements"); + std::string strat = prm.get("refinement strategy"); + if (strat == "global") + refinement_strategy = RefinementStrategy::refine_global; + else if (strat == "percentage") + refinement_strategy = RefinementStrategy::refine_percentage; + else if (strat == "fix dofs") + refinement_strategy = RefinementStrategy::refine_fix_dofs; + else + throw ExcNotImplemented(); + + n_cycles = prm.get_integer("number of cycles"); + obstacle_filename = prm.get("obstacle filename"); + output_dir = prm.get("output directory"); + if (output_dir!="" && *(output_dir.rbegin())!='/') + output_dir += "/"; + mkdir(output_dir.c_str(), 0777); + + transfer_solution = prm.get_bool("transfer solution"); + base_mesh = prm.get("base mesh"); + + pcout << " Using output directory '" << output_dir << "'" << std::endl; + pcout << " FE degree " << degree << std::endl; + pcout << " Obstacle '" << obstacle_filename << "'" << std::endl; + pcout << " transfer solution " << (transfer_solution?"true":"false") << std::endl; +} - // This is the implemented constitutive law. It projects the - // deviator part of the stresses in a quadrature point back to - // the yield stress plus the linear isotropic hardening. - // Also we sum up the elastic and the plastic quadrature - // points. - template - void ConstitutiveLaw::plast_linear_hardening (SymmetricTensor<4,dim> &stress_strain_tensor, - const SymmetricTensor<2,dim> &strain_tensor, - unsigned int &elast_points, - unsigned int &plast_points, - double &yield) - { - if (dim == 3) - { - SymmetricTensor<2,dim> stress_tensor; - stress_tensor = (stress_strain_tensor_kappa + stress_strain_tensor_mu)*strain_tensor; - - SymmetricTensor<2,dim> deviator_stress_tensor = deviator(stress_tensor); - - double deviator_stress_tensor_norm = deviator_stress_tensor.norm (); - - yield = 0; - stress_strain_tensor = stress_strain_tensor_mu; - double beta = 1.0; - if (deviator_stress_tensor_norm > sigma_0) - { - beta = sigma_0/deviator_stress_tensor_norm; - stress_strain_tensor *= (gamma + (1 - gamma)*beta); - yield = 1; - plast_points += 1; - } - else - elast_points += 1; +// @sect4{PlasticityContactProblem::declare} - stress_strain_tensor += stress_strain_tensor_kappa; - } - } +template +void +PlasticityContactProblem::declare(ParameterHandler &prm) +{ + prm.declare_entry("polynomial degree","1",Patterns::Integer(),"polynomial degree of the FE_Q finite element space, typically 1 or 2"); + prm.declare_entry("number of initial refinements","2",Patterns::Integer(),"number of initial global refinements before the first computation"); + prm.declare_entry("refinement strategy","percentage",Patterns::Selection("global|percentage|fix dofs"), + "refinement strategy for each cycle:\n" + " global: one global refinement\n" + "percentage: fixed percentage gets refined using kelly\n" + " fix dofs: tries to achieve 2^initial_refinement*300 dofs after cycle 1 (only use 2 cycles!). Changes the coarse mesh!"); + prm.declare_entry("number of cycles","5",Patterns::Integer(),"number of adaptive cycles to run"); + prm.declare_entry("obstacle filename","",Patterns::Anything(),"obstacle file to read, use 'obstacle_file.pbm' or leave empty to use a sphere"); + prm.declare_entry("output directory","",Patterns::Anything(),"directory to put output files (graphical output and benchmark statistics), leave empty to put into current directory"); + prm.declare_entry("transfer solution","false",Patterns::Bool(),"decide if the solution should be used as a starting guess for the finer mesh, use 0 otherwise."); + prm.declare_entry("base mesh","box",Patterns::Selection("box|half sphere"), + "select the shape of the work piece: 'box' or 'half sphere'"); + +} - // This function returns the linearized stress strain tensor. - // It contains the derivative of the nonlinear constitutive law. - template - void ConstitutiveLaw::linearized_plast_linear_hardening (SymmetricTensor<4,dim> &stress_strain_tensor_linearized, - SymmetricTensor<4,dim> &stress_strain_tensor, - const SymmetricTensor<2,dim> &strain_tensor) + Point<3> + rotate_half_sphere(const Point<3> &in) { - if (dim == 3) - { - SymmetricTensor<2,dim> stress_tensor; - stress_tensor = (stress_strain_tensor_kappa + stress_strain_tensor_mu)*strain_tensor; - - SymmetricTensor<2,dim> deviator_stress_tensor = deviator(stress_tensor); - - double deviator_stress_tensor_norm = deviator_stress_tensor.norm (); - - stress_strain_tensor = stress_strain_tensor_mu; - stress_strain_tensor_linearized = stress_strain_tensor_mu; - double beta = 1.0; - if (deviator_stress_tensor_norm > sigma_0) - { - beta = sigma_0/deviator_stress_tensor_norm; - stress_strain_tensor *= (gamma + (1 - gamma)*beta); - stress_strain_tensor_linearized *= (gamma + (1 - gamma)*beta); - deviator_stress_tensor /= deviator_stress_tensor_norm; - stress_strain_tensor_linearized -= (1 - gamma)*beta*2*mu*outer_product(deviator_stress_tensor, deviator_stress_tensor); - } - - stress_strain_tensor += stress_strain_tensor_kappa; - stress_strain_tensor_linearized += stress_strain_tensor_kappa; - } + return Point<3>(in(2), in(1), -in(0)); } - // In this namespace we provide three functions: - // one for the body force, one for the boundary displacement - // and one for the Obstacle. - namespace EquationData - { - // It possible to apply an additional body force - // but in here it is set to zero. - template - class RightHandSide : public Function - { - public: - RightHandSide () : Function(dim) {} - - virtual double value (const Point &p, - const unsigned int component = 0) const; - - virtual void vector_value (const Point &p, - Vector &values) const; - }; +// @sect4{PlasticityContactProblem::make_grid} + +template +void PlasticityContactProblem::make_grid() { - template - double RightHandSide::value (const Point &p, - const unsigned int component) const + if (base_mesh == "half sphere") { - double return_value = 0.0; - - if (component == 0) - return_value = 0.0; - if (component == 1) - return_value = 0.0; - if (component == 2) - return_value = 0.0; - - return return_value; + Point < dim > center(0, 0, 0); + double radius = 0.8; + GridGenerator::half_hyper_ball(triangulation, center, radius); + GridTools::transform(&rotate_half_sphere, triangulation); + Point < dim > shift(0.5, 0.5, 0.5); + GridTools::shift(shift, triangulation); + static HyperBallBoundary boundary_description(Point(0.5,0.5,0.5), radius); + triangulation.set_boundary (0, boundary_description); + + triangulation.refine_global(n_initial_refinements); + + to_refine_factor = 0.3; + to_coarsen_factor = 0.03; + return; } + + Point < dim > p1(0, 0, 0); + Point < dim > p2(1.0, 1.0, 1.0); + unsigned int ref = n_initial_refinements; - template - void RightHandSide::vector_value (const Point &p, - Vector &values) const + if (refinement_strategy == RefinementStrategy::refine_fix_dofs) { - for (unsigned int c=0; cn_components; ++c) - values(c) = RightHandSide::value (p, c); + /** + * This complicated logic creates a mesh and a refinement fraction to_refine_factor, + * so that the resulting mesh after adaptive refinement has approximately + * 2^n_refinements_global*300 dofs. This allows parallel scalability tests. + * About 5%-10% of the cells are being adaptively refined. + * We start with a 3x3,4x4, or 5x5 base mesh (whichever is closed in cell + * count). + */ + unsigned int ref = (n_initial_refinements + 1) / 3; + unsigned int remain = n_initial_refinements + 1 - ref * 3; + unsigned int rep = 3; + if (remain == 1) + rep = 4; + else if (remain == 2) + rep = 5; + + unsigned int n_cells_x = (1 << ref) * rep; + unsigned int goal_dofs = (1 << n_initial_refinements) * 300; + double goal_cells = std::pow(std::pow(goal_dofs / 3.0, 1.0 / 3.0) - 1.0, + 3.0); + double n_cells = std::pow(n_cells_x, 3.0); + to_refine_factor = (goal_cells - n_cells) / n_cells; + //convert from fraction of cells to add to fraction of cells to refine: + to_refine_factor /= 7.0; + to_coarsen_factor = 0.0; + + std::vector repet(3); + repet[0] = rep; + repet[1] = rep; + repet[2] = rep; + + GridGenerator::subdivided_hyper_rectangle(triangulation, repet, p1, p2); } - - // This function class is used to describe the prescribed displacements - // at the boundary. But again we set this to zero. - template - class BoundaryValues : public Function + else { - public: - BoundaryValues () : Function(dim) {}; - - virtual double value (const Point &p, - const unsigned int component = 0) const; + GridGenerator::hyper_rectangle(triangulation, p1, p2); + to_refine_factor = 0.3; + to_coarsen_factor = 0.03; + } - virtual void vector_value (const Point &p, - Vector &values) const; - }; - template - double BoundaryValues::value (const Point &p, - const unsigned int component) const - { - double return_value = 0; + Triangulation<3>::active_cell_iterator cell = triangulation.begin_active(), + endc = triangulation.end(); + + /* boundary_indicators: + _______ + / 1 /| + /______ / | + 8| | 8| + | 8 | / + |_______|/ + 6 + */ + + for (; cell != endc; ++cell) + for (unsigned int face = 0; + face < GeometryInfo < dim > ::faces_per_cell; ++face) { + if (cell->face(face)->center()[2] == p2(2)) + cell->face(face)->set_boundary_indicator(1); + if (cell->face(face)->center()[0] == p1(0) + || cell->face(face)->center()[0] == p2(0) + || cell->face(face)->center()[1] == p1(1) + || cell->face(face)->center()[1] == p2(1)) + cell->face(face)->set_boundary_indicator(8); + if (cell->face(face)->center()[2] == p1(2)) + cell->face(face)->set_boundary_indicator(6); + } + + triangulation.refine_global(ref); +} - if (component == 0) - return_value = 0.0; - if (component == 1) - return_value = 0.0; - if (component == 2) - return_value = 0.0; +template +void PlasticityContactProblem::setup_system() { + // setup dofs + { + TimerOutput::Scope t(computing_timer, "Setup: distribute DoFs"); + dof_handler.distribute_dofs(fe); + + locally_owned_dofs = dof_handler.locally_owned_dofs(); + locally_relevant_dofs.clear(); + DoFTools::extract_locally_relevant_dofs(dof_handler, + locally_relevant_dofs); + } + + // setup hanging nodes and dirichlet constraints + { + TimerOutput::Scope t(computing_timer, "Setup: constraints"); + constraints_hanging_nodes.reinit(locally_relevant_dofs); + DoFTools::make_hanging_node_constraints(dof_handler, + constraints_hanging_nodes); + constraints_hanging_nodes.close(); + + pcout << " Number of active cells: " + << triangulation.n_global_active_cells() << std::endl + << " Number of degrees of freedom: " << dof_handler.n_dofs() + << std::endl; + + dirichlet_constraints(); + } + + // Initialization for matrices and vectors + { + TimerOutput::Scope t(computing_timer, "Setup: vectors"); + solution.reinit(locally_relevant_dofs, mpi_communicator); + system_rhs_newton.reinit(locally_owned_dofs, mpi_communicator); + system_rhs_lambda.reinit(system_rhs_newton); + resid_vector.reinit(system_rhs_newton); + diag_mass_matrix_vector.reinit(system_rhs_newton); + cell_constitution.reinit(triangulation.n_active_cells()); + active_set.clear(); + active_set.set_size(locally_relevant_dofs.size()); + } + + // setup sparsity pattern + { + TimerOutput::Scope t(computing_timer, "Setup: matrix"); + TrilinosWrappers::SparsityPattern sp(locally_owned_dofs, + mpi_communicator); + + DoFTools::make_sparsity_pattern(dof_handler, sp, + constraints_dirichlet_hanging_nodes, false, + Utilities::MPI::this_mpi_process(mpi_communicator)); + + sp.compress(); + + system_matrix_newton.reinit(sp); + + // we are going to reuse the system + // matrix for assembling the diagonal + // of the mass matrix so that we do not + // need to allocate two sparse matrices + // at the same time: + TrilinosWrappers::SparseMatrix & mass_matrix = system_matrix_newton; + assemble_mass_matrix_diagonal(mass_matrix); + const unsigned int start = (system_rhs_newton.local_range().first), + end = (system_rhs_newton.local_range().second); + for (unsigned int j = start; j < end; j++) + diag_mass_matrix_vector(j) = mass_matrix.diag_element(j); + + number_iterations = 0; + + diag_mass_matrix_vector.compress(VectorOperation::insert); + + // remove the mass matrix entries from the matrix: + mass_matrix = 0; + } +} - return return_value; - } +template +void PlasticityContactProblem::assemble_nl_system( + TrilinosWrappers::MPI::Vector &u) { + TimerOutput::Scope t(computing_timer, "Assembling"); + + QGauss quadrature_formula(fe.degree + 1); + QGauss face_quadrature_formula(fe.degree + 1); + + FEValues < dim + > fe_values(fe, quadrature_formula, + UpdateFlags( + update_values | update_gradients | update_q_points + | update_JxW_values)); + + FEFaceValues < dim + > fe_values_face(fe, face_quadrature_formula, + update_values | update_quadrature_points + | update_JxW_values); + + const unsigned int dofs_per_cell = fe.dofs_per_cell; + const unsigned int n_q_points = quadrature_formula.size(); + const unsigned int n_face_q_points = face_quadrature_formula.size(); + + const EquationData::RightHandSide right_hand_side; + std::vector < Vector + > right_hand_side_values(n_q_points, Vector(dim)); + std::vector < Vector + > right_hand_side_values_face(n_face_q_points, Vector(dim)); + + FullMatrix cell_matrix(dofs_per_cell, dofs_per_cell); + Vector cell_rhs(dofs_per_cell); + + std::vector local_dof_indices(dofs_per_cell); + + typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(), endc = dof_handler.end(); + + const FEValuesExtractors::Vector displacement(0); + + const double kappa = 1.0; + for (; cell != endc; ++cell) + if (cell->is_locally_owned()) { + fe_values.reinit(cell); + cell_matrix = 0; + cell_rhs = 0; + + right_hand_side.vector_value_list(fe_values.get_quadrature_points(), + right_hand_side_values); + + std::vector < SymmetricTensor<2, dim> > strain_tensor(n_q_points); + fe_values[displacement].get_function_symmetric_gradients(u, + strain_tensor); + + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + SymmetricTensor < 4, dim > stress_strain_tensor_linearized; + SymmetricTensor < 4, dim > stress_strain_tensor; + SymmetricTensor < 2, dim > stress_tensor; + + plast_lin_hard->linearized_plast_linear_hardening( + stress_strain_tensor_linearized, stress_strain_tensor, + strain_tensor[q_point]); + + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + stress_tensor = stress_strain_tensor_linearized + * plast_lin_hard->get_strain(fe_values, i, q_point); + + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + cell_matrix(i, j) += (stress_tensor + * plast_lin_hard->get_strain(fe_values, j, + q_point) * fe_values.JxW(q_point)); + } + + // the linearized part a(v^i;v^i,v) of the rhs + cell_rhs(i) += (stress_tensor * strain_tensor[q_point] + * fe_values.JxW(q_point)); + + // the residual part a(v^i;v) of the rhs + cell_rhs(i) -= (strain_tensor[q_point] + * stress_strain_tensor + * plast_lin_hard->get_strain(fe_values, i, q_point) + * fe_values.JxW(q_point)); + + // the residual part F(v) of the rhs + Tensor < 1, dim > rhs_values; + rhs_values = 0; + cell_rhs(i) += (fe_values[displacement].value(i, q_point) + * rhs_values * fe_values.JxW(q_point)); + } + } + + for (unsigned int face = 0; + face < GeometryInfo < dim > ::faces_per_cell; ++face) { + if (cell->face(face)->at_boundary() + && cell->face(face)->boundary_indicator() == 1) { + fe_values_face.reinit(cell, face); + + right_hand_side.vector_value_list( + fe_values_face.get_quadrature_points(), + right_hand_side_values_face); + + for (unsigned int q_point = 0; q_point < n_face_q_points; + ++q_point) { + Tensor < 1, dim > rhs_values; + rhs_values[2] = right_hand_side_values[q_point][2]; + for (unsigned int i = 0; i < dofs_per_cell; ++i) + cell_rhs(i) += (fe_values_face[displacement].value( + i, q_point) * rhs_values + * fe_values_face.JxW(q_point)); + } + } + } + + cell->get_dof_indices(local_dof_indices); + constraints.distribute_local_to_global(cell_matrix, cell_rhs, + local_dof_indices, system_matrix_newton, system_rhs_newton, + true); + + + }; + + system_matrix_newton.compress(VectorOperation::add); + system_rhs_newton.compress(VectorOperation::add); +} - template - void BoundaryValues::vector_value (const Point &p, - Vector &values) const - { - for (unsigned int c=0; cn_components; ++c) - values(c) = BoundaryValues::value (p, c); - } +template +void PlasticityContactProblem::residual_nl_system( + TrilinosWrappers::MPI::Vector &u) { + QGauss quadrature_formula(fe.degree + 1); + QGauss face_quadrature_formula(fe.degree + 1); + + FEValues < dim + > fe_values(fe, quadrature_formula, + UpdateFlags( + update_values | update_gradients | update_q_points + | update_JxW_values)); + + FEFaceValues < dim + > fe_values_face(fe, face_quadrature_formula, + update_values | update_quadrature_points + | update_JxW_values); + + const unsigned int dofs_per_cell = fe.dofs_per_cell; + const unsigned int n_q_points = quadrature_formula.size(); + const unsigned int n_face_q_points = face_quadrature_formula.size(); + + const EquationData::RightHandSide right_hand_side; + std::vector < Vector + > right_hand_side_values(n_q_points, Vector(dim)); + std::vector < Vector + > right_hand_side_values_face(n_face_q_points, Vector(dim)); + + Vector cell_rhs(dofs_per_cell); + + std::vector local_dof_indices(dofs_per_cell); + + const FEValuesExtractors::Vector displacement(0); + + typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(), endc = dof_handler.end(); + + unsigned int elast_points = 0; + unsigned int plast_points = 0; + double yield = 0; + unsigned int cell_number = 0; + cell_constitution = 0; + + for (; cell != endc; ++cell) + if (cell->is_locally_owned()) { + fe_values.reinit(cell); + cell_rhs = 0; + + right_hand_side.vector_value_list(fe_values.get_quadrature_points(), + right_hand_side_values); + + std::vector < SymmetricTensor<2, dim> > strain_tensor(n_q_points); + fe_values[displacement].get_function_symmetric_gradients(u, + strain_tensor); + + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + SymmetricTensor < 4, dim > stress_strain_tensor; + SymmetricTensor < 2, dim > stress_tensor; + + plast_lin_hard->plast_linear_hardening(stress_strain_tensor, + strain_tensor[q_point], elast_points, plast_points, + yield); + + cell_constitution(cell_number) += yield; + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + cell_rhs(i) -= (strain_tensor[q_point] + * stress_strain_tensor + * //(stress_tensor) * + plast_lin_hard->get_strain(fe_values, i, q_point) + * fe_values.JxW(q_point)); + + Tensor < 1, dim > rhs_values; + rhs_values = 0; + cell_rhs(i) += ((fe_values[displacement].value(i, q_point) + * rhs_values) * fe_values.JxW(q_point)); + }; + }; + + for (unsigned int face = 0; + face < GeometryInfo < dim > ::faces_per_cell; ++face) { + if (cell->face(face)->at_boundary() + && cell->face(face)->boundary_indicator() == 1) { + fe_values_face.reinit(cell, face); + + right_hand_side.vector_value_list( + fe_values_face.get_quadrature_points(), + right_hand_side_values_face); + + for (unsigned int q_point = 0; q_point < n_face_q_points; + ++q_point) { + Tensor < 1, dim > rhs_values; + rhs_values[2] = right_hand_side_values[q_point][2]; + for (unsigned int i = 0; i < dofs_per_cell; ++i) + cell_rhs(i) += (fe_values_face[displacement].value( + i, q_point) * rhs_values + * fe_values_face.JxW(q_point)); + } + } + } + + cell->get_dof_indices(local_dof_indices); + constraints_dirichlet_hanging_nodes.distribute_local_to_global( + cell_rhs, local_dof_indices, system_rhs_newton); + + for (unsigned int i=0; i - class Obstacle : public Function - { - public: - Obstacle (std_cxx1x::shared_ptr > const &_input, bool _use_read_obstacle) : - Function(dim), - input_obstacle_copy(_input), - use_read_obstacle(_use_read_obstacle) - {} - - virtual double value (const Point &p, - const unsigned int component = 0) const; - - virtual void vector_value (const Point &p, - Vector &values) const; - - private: - std_cxx1x::shared_ptr > const &input_obstacle_copy; - bool use_read_obstacle; - }; - - template - double Obstacle::value (const Point &p, - const unsigned int component) const - { - double R = 0.03; - double return_value = 100.0; - if (component == 0) - return_value = p(0); - if (component == 1) - return_value = p(1); - if (component == 2) - { - if (use_read_obstacle) - return_value = 1.999 - input_obstacle_copy->obstacle_function (p(0), p(1)); - else - return_value = -std::sqrt (0.36 - (p(0)-0.5)*(p(0)-0.5) - (p(1)-0.5)*(p(1)-0.5)) + 1.59; - } - return return_value; - } +template +void PlasticityContactProblem::assemble_mass_matrix_diagonal( + TrilinosWrappers::SparseMatrix &mass_matrix) { + QGaussLobatto < dim - 1 > face_quadrature_formula(fe.degree + 1); + + FEFaceValues < dim + > fe_values_face(fe, face_quadrature_formula, + update_values | update_quadrature_points + | update_JxW_values); + + const unsigned int dofs_per_cell = fe.dofs_per_cell; + const unsigned int n_face_q_points = face_quadrature_formula.size(); + + FullMatrix cell_matrix(dofs_per_cell, dofs_per_cell); + Tensor<1, dim, double> ones(dim); + for (unsigned i = 0; i < dim; i++) + ones[i] = 1.0; + + std::vector local_dof_indices(dofs_per_cell); + + const FEValuesExtractors::Vector displacement(0); + + typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(), endc = dof_handler.end(); + + for (; cell != endc; ++cell) + if (cell->is_locally_owned()) + for (unsigned int face = 0; + face < GeometryInfo < dim > ::faces_per_cell; ++face) + if (cell->face(face)->at_boundary() + && cell->face(face)->boundary_indicator() == 1) { + fe_values_face.reinit(cell, face); + cell_matrix = 0; + + for (unsigned int q_point = 0; q_point < n_face_q_points; + ++q_point) + for (unsigned int i = 0; i < dofs_per_cell; ++i) + cell_matrix(i, i) += + (fe_values_face[displacement].value(i, + q_point) * ones + * fe_values_face.JxW(q_point)); + + cell->get_dof_indices(local_dof_indices); + +// constraints_dirichlet_hanging_nodes.distribute_local_to_global( +// cell_matrix, local_dof_indices, mass_matrix); + + for (unsigned int i=0; i - void Obstacle::vector_value (const Point &p, - Vector &values) const - { - for (unsigned int c=0; cn_components; ++c) - values(c) = Obstacle::value (p, c); - } - } +// @sect4{PlasticityContactProblem::update_solution_and_constraints} + +// Projection and updating of the active set +// for the dofs which penetrates the obstacle. +template +void PlasticityContactProblem::update_solution_and_constraints() { + const EquationData::Obstacle obstacle(input_obstacle, + (obstacle_filename!=""), + (base_mesh=="box"?1.0:0.5)); + std::vector vertex_touched(dof_handler.n_dofs(), false); + + typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(), endc = dof_handler.end(); + + TrilinosWrappers::MPI::Vector distributed_solution(system_rhs_newton); + distributed_solution = solution; + TrilinosWrappers::MPI::Vector lambda(solution); + lambda = resid_vector; + TrilinosWrappers::MPI::Vector diag_mass_matrix_vector_relevant(solution); + diag_mass_matrix_vector_relevant = diag_mass_matrix_vector; + + constraints.reinit(locally_relevant_dofs); + active_set.clear(); + IndexSet active_set_locally_owned; + active_set_locally_owned.set_size(locally_owned_dofs.size()); + const double c = 100.0 * e_modul; + + Quadrature face_quadrature (fe.get_unit_face_support_points()); + FEFaceValues fe_values_face (fe, face_quadrature, update_quadrature_points); + + const unsigned int dofs_per_face = fe.dofs_per_face; + const unsigned int n_face_q_points = face_quadrature.size (); + + // pcout<< "dofs_per_face = " << dofs_per_face + // << "n_face_q_points = " << n_face_q_points + // <is_artificial()) + for (unsigned int face = 0; + face < GeometryInfo < dim > ::faces_per_cell; ++face) + if (cell->face(face)->at_boundary() + && cell->face(face)->boundary_indicator() == 1) + { + fe_values_face.reinit (cell, face); + std::vector dof_indices (dofs_per_face); + cell->face(face)->get_dof_indices (dof_indices); + + for (unsigned int q_point=0; q_point point(fe_values_face.quadrature_point(q_point)); + + double obstacle_value = obstacle.value(point, 2); + double solution_index_z = solution(index_z); + double gap = obstacle_value - point(2); + + if (lambda(index_z)/diag_mass_matrix_vector_relevant(index_z) + + c * (solution_index_z - gap) > 0 + && !(constraints_hanging_nodes.is_constrained( + index_z))) { + constraints.add_line(index_z); + constraints.set_inhomogeneity(index_z, gap); + distributed_solution(index_z) = gap; + + if (locally_owned_dofs.is_element(index_z)) { + active_set_locally_owned.add_index(index_z); + if (locally_relevant_dofs.is_element(index_z)) + active_set.add_index(index_z); + } + + } + else if (lambda(index_z)/diag_mass_matrix_vector_relevant(index_z) + + c * (solution_index_z - gap) > 0 + && constraints_hanging_nodes.is_constrained( + index_z)) + { + if (locally_owned_dofs.is_element(index_z)) + { + counter_hanging_nodes += 1; + +// std::cout << "index_z = " << index_z +// << ", lambda = " << lambda (index_z) +// << ", solution_index_z - gap = " << solution_index_z - gap +// << ", diag_mass_matrix_vector_relevant = " << diag_mass_matrix_vector_relevant (index_z) +// << ", x = " << point(0) +// << ", y = " << point(1) +// << std::endl; + } + } + } + } + } + distributed_solution.compress(VectorOperation::insert); + + unsigned int sum_contact_constraints = Utilities::MPI::sum( + active_set_locally_owned.n_elements(), mpi_communicator); + pcout << " Size of active set: " << sum_contact_constraints + << std::endl; + unsigned int sum_contact_hanging_nodes = Utilities::MPI::sum( + counter_hanging_nodes, mpi_communicator); + pcout << " Number of hanging nodes in contact: " << sum_contact_hanging_nodes + << std::endl; + + solution = distributed_solution; + + constraints.close(); + + // constraints_dirichlet_hanging_nodes.print (std::cout); + + constraints.merge(constraints_dirichlet_hanging_nodes); + + //constraints.print (std::cout); +} - // @sect3{The PlasticityContactProblem class template} - - // This class supplies all function - // and variables needed to describe - // the nonlinear contact problem. It is - // close to step-41 but with some additional - // features like: handling hanging nodes, - // a Newton method, using Trilinos and p4est - // for parallel distributed computing. - // To deal with hanging nodes makes - // life a bit more complicated since - // we need an other ConstraintMatrix now. - // We create a Newton method for the - // active set method for the contact - // situation and to handle the nonlinear - // operator for the constitutive law. - - template - class PlasticityContactProblem - { - public: - PlasticityContactProblem (int _n_refinements_global); - void run (); - - private: - void make_grid (); - void setup_system(); - void assemble_nl_system (TrilinosWrappers::MPI::Vector &u); - void residual_nl_system (TrilinosWrappers::MPI::Vector &u); - void assemble_mass_matrix_diagonal (TrilinosWrappers::SparseMatrix &mass_matrix); - void update_solution_and_constraints (); - void dirichlet_constraints (); - void solve (); - void solve_newton (); - void refine_grid (); - void move_mesh (const TrilinosWrappers::MPI::Vector &_complete_displacement) const; - void output_results (const std::string &title) const; - - unsigned int n_refinements_global; - unsigned int cycle; - bool use_read_obstacle; - - MPI_Comm mpi_communicator; - - parallel::distributed::Triangulation triangulation; - - FESystem fe; - DoFHandler dof_handler; - - std_cxx1x::shared_ptr > soltrans; - - IndexSet locally_owned_dofs; - IndexSet locally_relevant_dofs; - - unsigned int number_iterations; - - ConstraintMatrix constraints; - ConstraintMatrix constraints_hanging_nodes; - ConstraintMatrix constraints_dirichlet_hanging_nodes; - - TrilinosWrappers::SparseMatrix system_matrix_newton; - - TrilinosWrappers::MPI::Vector solution; - TrilinosWrappers::MPI::Vector system_rhs_newton; - TrilinosWrappers::MPI::Vector resid_vector; - TrilinosWrappers::MPI::Vector diag_mass_matrix_vector; - Vector cell_constitution; - IndexSet active_set; - - ConditionalOStream pcout; - - TrilinosWrappers::PreconditionAMG::AdditionalData additional_data; - TrilinosWrappers::PreconditionAMG preconditioner_u; - - std_cxx1x::shared_ptr > input_obstacle; - std_cxx1x::shared_ptr > plast_lin_hard; - - double sigma_0; // Yield stress - double gamma; // Parameter for the linear isotropic hardening - double e_modul; // E-Modul - double nu; // Poisson ratio - - TimerOutput computing_timer; - }; - - // @sect3{Implementation of the PlasticityContactProblem class} - - // Next for the implementation of the class - // template that makes use of the functions - // above. As before, we will write everything - - template - PlasticityContactProblem::PlasticityContactProblem (int _n_refinements_global) - : - n_refinements_global (_n_refinements_global), - mpi_communicator (MPI_COMM_WORLD), - triangulation (mpi_communicator), - fe (FE_Q(1), dim), - dof_handler (triangulation), - pcout (std::cout, - (Utilities::MPI::this_mpi_process(mpi_communicator) == 0)), - sigma_0 (400), - gamma (0.01), - e_modul (2.0e+5), - nu (0.3), - computing_timer (MPI_COMM_WORLD, - pcout, - TimerOutput::never, - TimerOutput::wall_times) - { - plast_lin_hard.reset (new ConstitutiveLaw (e_modul, nu, sigma_0, gamma, mpi_communicator, pcout)); - } +// @sect4{PlasticityContactProblem::dirichlet_constraints} + +// This function defines the new ConstraintMatrix +// constraints_dirichlet_hanging_nodes. It contains +// the dirichlet boundary values as well as the +// hanging nodes constraints. +template +void PlasticityContactProblem::dirichlet_constraints() { + /* boundary_indicators: + _______ + / 1 /| + /______ / | + 8| | 8| + | 8 | / + |_______|/ + 6 + */ + + constraints_dirichlet_hanging_nodes.reinit(locally_relevant_dofs); + constraints_dirichlet_hanging_nodes.merge(constraints_hanging_nodes); + + // interpolate all components of the solution + VectorTools::interpolate_boundary_values(dof_handler, base_mesh=="box"?6:0, + EquationData::BoundaryValues(), + constraints_dirichlet_hanging_nodes, ComponentMask()); + + // interpolate x- and y-components of the + // solution (this is a bit mask, so apply + // operator| ) + FEValuesExtractors::Scalar x_displacement(0); + FEValuesExtractors::Scalar y_displacement(1); + VectorTools::interpolate_boundary_values(dof_handler, 8, + EquationData::BoundaryValues(), + constraints_dirichlet_hanging_nodes, + (fe.component_mask(x_displacement) + | fe.component_mask(y_displacement))); + constraints_dirichlet_hanging_nodes.close(); +} - template - void PlasticityContactProblem::make_grid () - { - std::vector repet(3); - repet[0] = 1; - repet[1] = 1; - repet[2] = 1; - - Point p1 (0,0,0); - Point p2 (1.0, 1.0, 1.0); - GridGenerator::subdivided_hyper_rectangle (triangulation, repet, p1, p2); - - Triangulation<3>::active_cell_iterator - cell = triangulation.begin_active(), - endc = triangulation.end(); - - /* boundary_indicators: - _______ - / 9 /| - /______ / | - 8| | 8| - | 8 | / - |_______|/ - 6 - */ - - for (; cell!=endc; ++cell) - for (unsigned int face=0; face::faces_per_cell; ++face) - { - if (cell->face (face)->center ()[2] == p2(2)) - cell->face (face)->set_boundary_indicator (9); - if (cell->face (face)->center ()[0] == p1(0) || - cell->face (face)->center ()[0] == p2(0) || - cell->face (face)->center ()[1] == p1(1) || - cell->face (face)->center ()[1] == p2(1)) - cell->face (face)->set_boundary_indicator (8); - if (cell->face (face)->center ()[2] == p1(2)) - cell->face (face)->set_boundary_indicator (6); - } - - triangulation.refine_global (n_refinements_global); - } +// @sect4{PlasticityContactProblem::solve} - // In following function we setup the degrees of freedom before each refinement - // cycle. Except that we are using Trilinos here instead of PETSc most of it - // is similar to step-40. +// In addition to step-41 we have +// to deal with the hanging node +// constraints. Again we also consider +// the locally_owned_dofs only by +// creating the vector distributed_solution. +// +// For the hanging nodes we have to apply +// the set_zero function to system_rhs_newton. +// This is necessary if a hanging node value x_0 +// has one neighbor which is in contact with +// value x_0 and one neighbor which is not with +// value x_1. This leads to an inhomogeneity +// constraint with value x_1/2 = gap/2 in the +// ConstraintMatrix. +// So the corresponding entries in the +// ride-hang-side are non-zero with a +// meaningless value. These values have to +// to set to zero. + +// The rest of the function is similar to +// step-41 except that we use a FGMRES-solver +// instead of CG. For a very small hardening +// value gamma the linear system becomes +// almost semi definite but still symmetric. +template +void PlasticityContactProblem::solve() { + TimerOutput::Scope t(computing_timer, "Solve"); + + TrilinosWrappers::MPI::Vector distributed_solution(system_rhs_newton); + distributed_solution = solution; + + constraints_hanging_nodes.set_zero(distributed_solution); + constraints_hanging_nodes.set_zero(system_rhs_newton); + distributed_solution.compress(VectorOperation::insert); + system_rhs_newton.compress(VectorOperation::insert); + + { + TimerOutput::Scope t(computing_timer, "Solve: setup preconditioner"); + preconditioner_u.initialize(system_matrix_newton, additional_data); + } + + { + TimerOutput::Scope t(computing_timer, "Solve: iterate"); + + PrimitiveVectorMemory < TrilinosWrappers::MPI::Vector > mem; + TrilinosWrappers::MPI::Vector tmp(system_rhs_newton); + // 1e-4 seems to be the fasted option altogether, but to get more + // reproducible parallel benchmark results, we use a small residual: + double relative_accuracy = 1e-8; + if (output_dir.compare("its/") == 0) + relative_accuracy = 1e-4; + + const double solver_tolerance = relative_accuracy + * system_matrix_newton.residual(tmp, distributed_solution, + system_rhs_newton); + + SolverControl solver_control(system_matrix_newton.m(), + solver_tolerance); + SolverBicgstab < TrilinosWrappers::MPI::Vector + > solver(solver_control, mem/*, + SolverFGMRES:: + AdditionalData(30, true)*/); + solver.solve(system_matrix_newton, distributed_solution, + system_rhs_newton, preconditioner_u); + + pcout << " Error: " << solver_control.initial_value() << " -> " + << solver_control.last_value() << " in " + << solver_control.last_step() << " Bicgstab iterations." + << std::endl; + + number_iterations += solver_control.last_step(); + } + + constraints.distribute(distributed_solution); + + solution = distributed_solution; +} - // We are using TimerOutput to control the scaling for the distributing the dofs - // and setting of the sparsity pattern and the system matrix. - template - void PlasticityContactProblem::setup_system () - { - { - computing_timer.enter_section("Setup: distribute DoFs"); - dof_handler.distribute_dofs (fe); - - locally_owned_dofs = dof_handler.locally_owned_dofs (); - locally_relevant_dofs.clear(); - DoFTools::extract_locally_relevant_dofs (dof_handler, - locally_relevant_dofs); - computing_timer.exit_section("Setup: distribute DoFs"); - } +// @sect4{PlasticityContactProblem::solve_newton} + +// In this function the damped Newton method is implemented. +// That means two nested loops: the outer loop for the newton +// iteration and the inner loop for the damping steps which +// will be used only if necessary. To obtain a good and reasonable +// starting value we solve an elastic problem in very first step (j=1). +template +void PlasticityContactProblem::solve_newton() { + TimerOutput::Scope t(computing_timer, "solve newton setup"); + + double resid = 0; + double resid_old = 100000; + TrilinosWrappers::MPI::Vector old_solution(system_rhs_newton); + TrilinosWrappers::MPI::Vector res(system_rhs_newton); + TrilinosWrappers::MPI::Vector tmp_vector(system_rhs_newton); + + std::vector < std::vector > constant_modes; + DoFTools::extract_constant_modes(dof_handler, ComponentMask(), + constant_modes); + + double sigma_hlp = sigma_0; + + additional_data.constant_modes = constant_modes; + additional_data.elliptic = true; + additional_data.n_cycles = 1; + additional_data.w_cycle = false; + additional_data.output_details = false; + additional_data.smoother_sweeps = 2; + additional_data.aggregation_threshold = 1e-2; + + IndexSet active_set_old(active_set); + + t.stop(); // stop newton setup timer + + unsigned int j = 1; + unsigned int number_assemble_system = 0; + for (; j <= 100; j++) { + if (transfer_solution) + { + if (transfer_solution && j == 1 && cycle == 0) + plast_lin_hard->set_sigma_0(1e+10); + else if (transfer_solution && (j == 2 || cycle > 0)) + plast_lin_hard->set_sigma_0(sigma_hlp); + } + else + { + if (j == 1) + plast_lin_hard->set_sigma_0(1e+10); + else + plast_lin_hard->set_sigma_0(sigma_hlp); + } + + pcout << " " << std::endl; + pcout << " Newton iteration " << j << std::endl; + pcout << " Updating active set..." << std::endl; + + { + TimerOutput::Scope t(computing_timer, "update active set"); + update_solution_and_constraints(); + } + + pcout << " Assembling system... " << std::endl; + system_matrix_newton = 0; + system_rhs_newton = 0; + assemble_nl_system(solution); //compute Newton-Matrix + + number_assemble_system += 1; + + pcout << " Solving system... " << std::endl; + solve(); + + TrilinosWrappers::MPI::Vector distributed_solution(system_rhs_newton); + distributed_solution = solution; + + // We handle a highly nonlinear problem so we have to damp + // the Newtons method. We refer that we iterate the new solution + // in each Newton step and not only the solution update. + // Since the solution set is a convex set and not a space we + // compute for the damping a linear combination of the + // previous and the current solution to guarantee that the + // damped solution is in our solution set again. + // At most we apply 10 damping steps. + bool damped = false; + tmp_vector = old_solution; + double a = 0; + for (unsigned int i = 0; (i < 5) && (!damped); i++) { + a = std::pow(0.5, static_cast(i)); + old_solution = tmp_vector; + old_solution.sadd(1 - a, a, distributed_solution); + old_solution.compress(VectorOperation::add); + + TimerOutput::Scope t(computing_timer, "Residual and lambda"); + + system_rhs_newton = 0; + system_rhs_lambda = 0; + + solution = old_solution; + residual_nl_system(solution); + res = system_rhs_newton; + + const unsigned int start_res = (res.local_range().first), end_res = + (res.local_range().second); + for (unsigned int n = start_res; n < end_res; ++n) + if (constraints.is_inhomogeneously_constrained(n)) + res(n) = 0; + + res.compress(VectorOperation::insert); + + resid = res.l2_norm(); + + if (resid < resid_old) + damped = true; + + pcout << " Residual of the non-contact part of the system: " + << resid << std::endl + << " with a damping parameter alpha = " << a + << std::endl; + + // The previous iteration of step 0 is the solution of an elastic problem. + // So a linear combination of a plastic and an elastic solution makes no sense + // since the elastic solution is not in the convex set of the plastic solution. + if (!transfer_solution && j == 2) + break; + if (transfer_solution && j == 2 && cycle == 0) + break; + } + + resid_old = resid; + + resid_vector = system_rhs_lambda; + resid_vector.compress(VectorOperation::insert); + + int is_my_set_changed = (active_set == active_set_old) ? 0 : 1; + int num_changed = Utilities::MPI::sum(is_my_set_changed, + MPI_COMM_WORLD); + if (num_changed == 0) + { + pcout<< " Active set did not change!" <refine_grid function} - // Initialization for matrices and vectors. +template +void PlasticityContactProblem::refine_grid() { + if (refinement_strategy == RefinementStrategy::refine_global) { - solution.reinit (locally_relevant_dofs, mpi_communicator); - system_rhs_newton.reinit (locally_owned_dofs, mpi_communicator); - resid_vector.reinit (system_rhs_newton); - diag_mass_matrix_vector.reinit (system_rhs_newton); - cell_constitution.reinit (triangulation.n_active_cells ()); - active_set.clear (); - active_set.set_size (locally_relevant_dofs.size ()); + triangulation.refine_global(1); } - - // Here we setup sparsity pattern. + else { - computing_timer.enter_section("Setup: matrix"); - TrilinosWrappers::SparsityPattern sp (locally_owned_dofs, - mpi_communicator); + Vector estimated_error_per_cell(triangulation.n_active_cells()); + KellyErrorEstimator < dim + > ::estimate(dof_handler, QGauss < dim - 1 > (fe.degree + 2), + typename FunctionMap::type(), solution, + estimated_error_per_cell); - DoFTools::make_sparsity_pattern (dof_handler, sp, constraints_dirichlet_hanging_nodes, false, - Utilities::MPI::this_mpi_process(mpi_communicator)); + parallel::distributed::GridRefinement::refine_and_coarsen_fixed_number( + triangulation, estimated_error_per_cell, 0.3, 0.03); - sp.compress(); + triangulation.prepare_coarsening_and_refinement(); + if (transfer_solution) + soltrans->prepare_for_coarsening_and_refinement(solution); - system_matrix_newton.reinit (sp); - - // we are going to reuse the system - // matrix for assembling the diagonal - // of the mass matrix so that we do not - // need to allocate two sparse matrices - // at the same time: - TrilinosWrappers::SparseMatrix &mass_matrix = system_matrix_newton; - assemble_mass_matrix_diagonal (mass_matrix); - const unsigned int - start = (system_rhs_newton.local_range().first), - end = (system_rhs_newton.local_range().second); - for (unsigned int j=start; j - void PlasticityContactProblem::assemble_nl_system (TrilinosWrappers::MPI::Vector &u) - { - computing_timer.enter_section("Assembling"); - - QGauss quadrature_formula(2); - QGauss face_quadrature_formula(2); - - FEValues fe_values (fe, quadrature_formula, - UpdateFlags(update_values | - update_gradients | - update_q_points | - update_JxW_values)); - - FEFaceValues fe_values_face (fe, face_quadrature_formula, - update_values | update_quadrature_points | - update_JxW_values); - - const unsigned int dofs_per_cell = fe.dofs_per_cell; - const unsigned int n_q_points = quadrature_formula.size (); - const unsigned int n_face_q_points = face_quadrature_formula.size(); - - const EquationData::RightHandSide right_hand_side; - std::vector > right_hand_side_values (n_q_points, - Vector(dim)); - std::vector > right_hand_side_values_face (n_face_q_points, - Vector(dim)); - - FullMatrix cell_matrix (dofs_per_cell, dofs_per_cell); - Vector cell_rhs (dofs_per_cell); - - std::vector local_dof_indices (dofs_per_cell); - - typename DoFHandler::active_cell_iterator cell = dof_handler.begin_active(), - endc = dof_handler.end(); - - const FEValuesExtractors::Vector displacement (0); - - const double kappa = 1.0; - for (; cell!=endc; ++cell) - if (cell->is_locally_owned()) - { - fe_values.reinit (cell); - cell_matrix = 0; - cell_rhs = 0; - - right_hand_side.vector_value_list (fe_values.get_quadrature_points(), - right_hand_side_values); - - std::vector > strain_tensor (n_q_points); - fe_values[displacement].get_function_symmetric_gradients (u, strain_tensor); - - for (unsigned int q_point=0; q_point stress_strain_tensor_linearized; - SymmetricTensor<4,dim> stress_strain_tensor; - SymmetricTensor<2,dim> stress_tensor; - - plast_lin_hard->linearized_plast_linear_hardening (stress_strain_tensor_linearized, - stress_strain_tensor, - strain_tensor[q_point]); - - for (unsigned int i=0; iget_strain(fe_values, i, q_point); - - for (unsigned int j=0; jget_strain(fe_values, j, q_point) * - fe_values.JxW (q_point)); - } - - // the linearized part a(v^i;v^i,v) of the rhs - cell_rhs(i) += (stress_tensor * - strain_tensor[q_point] * - fe_values.JxW (q_point)); - - // the residual part a(v^i;v) of the rhs - cell_rhs(i) -= (strain_tensor[q_point] * stress_strain_tensor * - plast_lin_hard->get_strain(fe_values, i, q_point) * - fe_values.JxW (q_point)); - - // the residual part F(v) of the rhs - Tensor<1,dim> rhs_values; - rhs_values = 0; - cell_rhs(i) += (fe_values[displacement].value (i, q_point) * - rhs_values * - fe_values.JxW (q_point)); - } - } - - for (unsigned int face=0; face::faces_per_cell; ++face) - { - if (cell->face (face)->at_boundary() - && cell->face (face)->boundary_indicator () == 9) - { - fe_values_face.reinit (cell, face); - - right_hand_side.vector_value_list (fe_values_face.get_quadrature_points(), - right_hand_side_values_face); - - for (unsigned int q_point=0; q_point rhs_values; - rhs_values = 0; - for (unsigned int i=0; iget_dof_indices (local_dof_indices); - constraints.distribute_local_to_global (cell_matrix, cell_rhs, - local_dof_indices, - system_matrix_newton, system_rhs_newton, true); - }; - - system_matrix_newton.compress (VectorOperation::add); - system_rhs_newton.compress (VectorOperation::add); - - computing_timer.exit_section("Assembling"); - } - - template - void PlasticityContactProblem::residual_nl_system (TrilinosWrappers::MPI::Vector &u) - { - QGauss quadrature_formula(2); - QGauss face_quadrature_formula(2); - - FEValues fe_values (fe, quadrature_formula, - UpdateFlags(update_values | - update_gradients | - update_q_points | - update_JxW_values)); - - FEFaceValues fe_values_face (fe, face_quadrature_formula, - update_values | update_quadrature_points | - update_JxW_values); - - const unsigned int dofs_per_cell = fe.dofs_per_cell; - const unsigned int n_q_points = quadrature_formula.size (); - const unsigned int n_face_q_points = face_quadrature_formula.size(); - - const EquationData::RightHandSide right_hand_side; - std::vector > right_hand_side_values (n_q_points, - Vector(dim)); - std::vector > right_hand_side_values_face (n_face_q_points, - Vector(dim)); - - Vector cell_rhs (dofs_per_cell); - - std::vector local_dof_indices (dofs_per_cell); - - const FEValuesExtractors::Vector displacement (0); - - typename DoFHandler::active_cell_iterator cell = dof_handler.begin_active(), - endc = dof_handler.end(); - - unsigned int elast_points = 0; - unsigned int plast_points = 0; - double yield = 0; - unsigned int cell_number = 0; - cell_constitution = 0; - - for (; cell!=endc; ++cell) - if (cell->is_locally_owned()) - { - fe_values.reinit (cell); - cell_rhs = 0; - - right_hand_side.vector_value_list (fe_values.get_quadrature_points(), - right_hand_side_values); - - std::vector > strain_tensor (n_q_points); - fe_values[displacement].get_function_symmetric_gradients (u, strain_tensor); - - for (unsigned int q_point=0; q_point stress_strain_tensor; - SymmetricTensor<2,dim> stress_tensor; - - plast_lin_hard->plast_linear_hardening (stress_strain_tensor, strain_tensor[q_point], - elast_points, plast_points, yield); - - cell_constitution (cell_number) += yield; - for (unsigned int i=0; iget_strain(fe_values, i, q_point) * - fe_values.JxW (q_point)); - - Tensor<1,dim> rhs_values; - rhs_values = 0; - cell_rhs(i) += ((fe_values[displacement].value (i, q_point) * - rhs_values) * - fe_values.JxW (q_point)); - }; - }; - - for (unsigned int face=0; face::faces_per_cell; ++face) - { - if (cell->face (face)->at_boundary() - && cell->face (face)->boundary_indicator () == 9) - { - fe_values_face.reinit (cell, face); - - right_hand_side.vector_value_list (fe_values_face.get_quadrature_points(), - right_hand_side_values_face); - - for (unsigned int q_point=0; q_point rhs_values; - rhs_values = 0; - for (unsigned int i=0; iget_dof_indices (local_dof_indices); - constraints_dirichlet_hanging_nodes.distribute_local_to_global (cell_rhs, - local_dof_indices, - system_rhs_newton); - - cell_number += 1; - } - else - { - cell_constitution (cell_number) = 0; - cell_number += 1; - }; - - cell_constitution /= n_q_points; - cell_constitution.compress (VectorOperation::add); - system_rhs_newton.compress (VectorOperation::add); - - unsigned int sum_elast_points = Utilities::MPI::sum(elast_points, mpi_communicator); - unsigned int sum_plast_points = Utilities::MPI::sum(plast_points, mpi_communicator); - pcout << " Number of elastic quadrature points: " << sum_elast_points - << " and plastic quadrature points: " << sum_plast_points << std::endl; - } - - template - void PlasticityContactProblem::assemble_mass_matrix_diagonal (TrilinosWrappers::SparseMatrix &mass_matrix) - { - QTrapez face_quadrature_formula; - - FEFaceValues fe_values_face (fe, face_quadrature_formula, - update_values | - update_quadrature_points | - update_JxW_values); - - const unsigned int dofs_per_cell = fe.dofs_per_cell; - const unsigned int n_face_q_points = face_quadrature_formula.size(); - - FullMatrix cell_matrix (dofs_per_cell, dofs_per_cell); - Tensor<1,dim,double> ones (dim); - for (unsigned i=0; i local_dof_indices (dofs_per_cell); - - const FEValuesExtractors::Vector displacement (0); - - typename DoFHandler::active_cell_iterator - cell = dof_handler.begin_active(), - endc = dof_handler.end(); - - for (; cell!=endc; ++cell) - if (cell->is_locally_owned()) - for (unsigned int face=0; face::faces_per_cell; ++face) - if (cell->face (face)->at_boundary() - && cell->face (face)->boundary_indicator () == 9) - { - fe_values_face.reinit (cell, face); - cell_matrix = 0; - - for (unsigned int q_point=0; q_pointget_dof_indices (local_dof_indices); - - constraints_dirichlet_hanging_nodes.distribute_local_to_global (cell_matrix, - local_dof_indices, - mass_matrix); - } - - mass_matrix.compress (VectorOperation::add); - } - - // @sect4{PlasticityContactProblem::update_solution_and_constraints} - - // Projection and updating of the active set - // for the dofs which penetrates the obstacle. - template - void PlasticityContactProblem::update_solution_and_constraints () - { - computing_timer.enter_section("Update solution and constraints"); - - const EquationData::Obstacle obstacle (input_obstacle, use_read_obstacle); - std::vector vertex_touched (dof_handler.n_dofs (), false); - - typename DoFHandler::active_cell_iterator - cell = dof_handler.begin_active(), - endc = dof_handler.end(); - - TrilinosWrappers::MPI::Vector distributed_solution (system_rhs_newton); - distributed_solution = solution; - TrilinosWrappers::MPI::Vector lambda (solution); - lambda = resid_vector; - TrilinosWrappers::MPI::Vector diag_mass_matrix_vector_relevant (solution); - diag_mass_matrix_vector_relevant = diag_mass_matrix_vector; - - constraints.reinit(locally_relevant_dofs); - active_set.clear (); - IndexSet active_set_locally_owned; - active_set_locally_owned.set_size (locally_owned_dofs.size ()); - const double c = 100.0*e_modul; - - for (; cell!=endc; ++cell) - if (cell->is_locally_owned()) - for (unsigned int face=0; face::faces_per_cell; ++face) - if (cell->face (face)->at_boundary() - && cell->face (face)->boundary_indicator () == 9) - for (unsigned int v=0; v::vertices_per_cell; ++v) - { - unsigned int index_z = cell->face (face)->vertex_dof_index (v,2); - - if (vertex_touched[cell->face (face)->vertex_index(v)] == false) - vertex_touched[cell->face (face)->vertex_index(v)] = true; - else - continue; - - // the local row where - Point point (cell->face (face)->vertex (v)[0], - cell->face (face)->vertex (v)[1], - cell->face (face)->vertex (v)[2]); - - double obstacle_value = obstacle.value (point, 2); - double solution_index_z = solution (index_z); - double gap = obstacle_value - point (2); - - -// std::cout << "lambda = " << lambda (index_z) -// << ", solution_index_z - gap = " << solution_index_z - gap -// << ", diag_mass_matrix_vector_relevant = " << diag_mass_matrix_vector_relevant (index_z) -// << std::endl; - - if (lambda (index_z) + - c * - diag_mass_matrix_vector_relevant (index_z) * - (solution_index_z - gap) - > 0 && - !(constraints_hanging_nodes.is_constrained(index_z))) - { - constraints.add_line (index_z); - constraints.set_inhomogeneity (index_z, gap); - - distributed_solution (index_z) = gap; - - if (locally_relevant_dofs.is_element (index_z)) - active_set.add_index (index_z); - - if (locally_owned_dofs.is_element (index_z)) - active_set_locally_owned.add_index (index_z); - } - } - distributed_solution.compress (VectorOperation::insert); - - unsigned int sum_contact_constraints = Utilities::MPI::sum(active_set_locally_owned.n_elements (), - mpi_communicator); - pcout << " Size of active set: " << sum_contact_constraints < - void PlasticityContactProblem::dirichlet_constraints () - { - /* boundary_indicators: - _______ - / 9 /| - /______ / | - 8| | 8| - | 8 | / - |_______|/ - 6 - */ - - constraints_dirichlet_hanging_nodes.reinit (locally_relevant_dofs); - constraints_dirichlet_hanging_nodes.merge (constraints_hanging_nodes); - - // interpolate all components of the solution - VectorTools::interpolate_boundary_values (dof_handler, - 6, - EquationData::BoundaryValues(), - constraints_dirichlet_hanging_nodes, - ComponentMask()); - - // interpolate x- and y-components of the - // solution (this is a bit mask, so apply - // operator| ) - FEValuesExtractors::Scalar x_displacement(0); - FEValuesExtractors::Scalar y_displacement(1); - VectorTools::interpolate_boundary_values (dof_handler, - 8, - EquationData::BoundaryValues(), - constraints_dirichlet_hanging_nodes, - (fe.component_mask(x_displacement) - | - fe.component_mask(y_displacement))); - constraints_dirichlet_hanging_nodes.close (); - } - - // @sect4{PlasticityContactProblem::solve} - - // In addition to step-41 we have - // to deal with the hanging node - // constraints. Again we also consider - // the locally_owned_dofs only by - // creating the vector distributed_solution. - // - // For the hanging nodes we have to apply - // the set_zero function to system_rhs_newton. - // This is necessary if a hanging node value x_0 - // has one neighbor which is in contact with - // value x_0 and one neighbor which is not with - // value x_1. This leads to an inhomogeneity - // constraint with value x_1/2 = gap/2 in the - // ConstraintMatrix. - // So the corresponding entries in the - // ride-hang-side are non-zero with a - // meaningless value. These values have to - // to set to zero. - - // The rest of the function is similar to - // step-41 except that we use a FGMRES-solver - // instead of CG. For a very small hardening - // value gamma the linear system becomes - // almost semi definite but still symmetric. - template - void PlasticityContactProblem::solve () - { - computing_timer.enter_section ("Solve"); - - TrilinosWrappers::MPI::Vector distributed_solution (system_rhs_newton); - distributed_solution = solution; - - constraints_hanging_nodes.set_zero (distributed_solution); - constraints_hanging_nodes.set_zero (system_rhs_newton); - distributed_solution.compress(VectorOperation::insert); - system_rhs_newton.compress(VectorOperation::insert); - - computing_timer.enter_section("Solve: setup preconditioner"); - - preconditioner_u.initialize (system_matrix_newton, additional_data); - - computing_timer.exit_section("Solve: setup preconditioner"); - - computing_timer.enter_section("Solve: iterate"); - - PrimitiveVectorMemory mem; - TrilinosWrappers::MPI::Vector tmp (system_rhs_newton); - const double solver_tolerance = 1e-3 * - system_matrix_newton.residual (tmp, distributed_solution, system_rhs_newton); - -// SolverControl solver_control (system_matrix_newton.m(), solver_tolerance); -// SolverFGMRES -// solver(solver_control, mem, -// SolverFGMRES:: -// AdditionalData(30, true)); -// -// solver.solve(system_matrix_newton, distributed_solution, system_rhs_newton, preconditioner_u); -// -// pcout << " Error: " << solver_control.initial_value() -// << " -> " << solver_control.last_value() -// << " in " << solver_control.last_step() -// << " FGMRES iterations." -// << std::endl; - - SolverControl solver_control (system_matrix_newton.m(), solver_tolerance); - SolverBicgstab - solver(solver_control, mem, - SolverBicgstab:: - AdditionalData(false, 1.e-10)); - - solver.solve(system_matrix_newton, distributed_solution, system_rhs_newton, preconditioner_u); - - pcout << " Error: " << solver_control.initial_value() - << " -> " << solver_control.last_value() - << " in " << solver_control.last_step() - << " Bicgstab iterations." - << std::endl; - - computing_timer.exit_section("Solve: iterate"); - - number_iterations += solver_control.last_step(); - - constraints.distribute (distributed_solution); - - solution = distributed_solution; - - computing_timer.exit_section("Solve"); - } - - // @sect4{PlasticityContactProblem::solve_newton} - - // In this function the damped Newton method is implemented. - // That means two nested loops: the outer loop for the newton - // iteration and the inner loop for the damping steps which - // will be used only if necessary. To obtain a good and reasonable - // starting value we solve an elastic problem in very first step (j=1). - template - void PlasticityContactProblem::solve_newton () - { - double resid=0; - double resid_old=100000; - TrilinosWrappers::MPI::Vector old_solution (system_rhs_newton); - TrilinosWrappers::MPI::Vector res (system_rhs_newton); - TrilinosWrappers::MPI::Vector tmp_vector (system_rhs_newton); - - std::vector > constant_modes; - DoFTools::extract_constant_modes (dof_handler, - ComponentMask(), - constant_modes); - - double sigma_hlp = sigma_0; - - additional_data.constant_modes = constant_modes; - additional_data.elliptic = true; - additional_data.n_cycles = 1; - additional_data.w_cycle = false; - additional_data.output_details = false; - additional_data.smoother_sweeps = 2; - additional_data.aggregation_threshold = 1e-2; - - IndexSet active_set_old (active_set); - unsigned int j = 1; - unsigned int number_assemble_system = 0; - for (; j<=100; j++) - { - if (j == 1 && cycle == 0) - plast_lin_hard->set_sigma_0 (1e+10); - else if (j == 2 || cycle > 0) - plast_lin_hard->set_sigma_0 (sigma_hlp); - - pcout << " " <(i)); - old_solution = tmp_vector; - old_solution.sadd(1-a,a, distributed_solution); - old_solution.compress (VectorOperation::add); - - computing_timer.enter_section("Residual and lambda"); - - system_rhs_newton = 0; - - solution = old_solution; - residual_nl_system (solution); - res = system_rhs_newton; - - const unsigned int - start_res = (res.local_range().first), - end_res = (res.local_range().second); - for (unsigned int n=start_res; n::type_dof_data, - data_component_interpretation); - data_out.add_data_vector (lambda, std::vector(dim, "Residual"), - DataOut::type_dof_data, - data_component_interpretation); - data_out.add_data_vector (active_set, std::vector(dim, "ActiveSet"), - DataOut::type_dof_data, - data_component_interpretation); - - Vector subdomain (triangulation.n_active_cells()); - for (unsigned int i=0; i filenames; - for (unsigned int i=0; - imove_mesh function} + +template +void PlasticityContactProblem::move_mesh( + const TrilinosWrappers::MPI::Vector &_complete_displacement) const { + std::vector vertex_touched(triangulation.n_vertices(), false); + + for (typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell) + if (cell->is_locally_owned()) + for (unsigned int v = 0; + v < GeometryInfo < dim > ::vertices_per_cell; ++v) { + if (vertex_touched[cell->vertex_index(v)] == false) { + vertex_touched[cell->vertex_index(v)] = true; + + Point < dim > vertex_displacement; + for (unsigned int d = 0; d < dim; ++d) { + if (_complete_displacement(cell->vertex_dof_index(v, d)) + != 0) + vertex_displacement[d] = _complete_displacement( + cell->vertex_dof_index(v, d)); + } + + cell->vertex(v) += vertex_displacement; + } + } +} +// @sect4{PlasticityContactProblem::output_results} + +template +void PlasticityContactProblem::output_results( + const std::string &title) { + move_mesh(solution); + + // Calculation of the contact forces + TrilinosWrappers::MPI::Vector lambda(solution); + TrilinosWrappers::MPI::Vector distributed_lambda(system_rhs_newton); + const unsigned int start_res = (resid_vector.local_range().first), end_res = + (resid_vector.local_range().second); + for (unsigned int n = start_res; n < end_res; ++n) + if (constraints.is_inhomogeneously_constrained(n)) + distributed_lambda(n) = resid_vector(n)/diag_mass_matrix_vector(n); + distributed_lambda.compress(VectorOperation::insert); + constraints_hanging_nodes.distribute(distributed_lambda); + lambda = distributed_lambda; + TrilinosWrappers::MPI::Vector resid_vector_relevant(solution); + TrilinosWrappers::MPI::Vector distributed_resid_vector(resid_vector); + constraints_hanging_nodes.distribute(distributed_resid_vector); + resid_vector_relevant = distributed_resid_vector; + + DataOut < dim > data_out; + + data_out.attach_dof_handler(dof_handler); + + const std::vector data_component_interpretation( + dim, DataComponentInterpretation::component_is_part_of_vector); + data_out.add_data_vector(solution, + std::vector < std::string > (dim, "Displacement"), + DataOut < dim > ::type_dof_data, data_component_interpretation); + data_out.add_data_vector(lambda, + std::vector < std::string > (dim, "ContactForce"), + DataOut < dim > ::type_dof_data, data_component_interpretation); + data_out.add_data_vector(active_set, + std::vector < std::string > (dim, "ActiveSet"), + DataOut < dim > ::type_dof_data, data_component_interpretation); + data_out.add_data_vector(resid_vector_relevant, + std::vector < std::string > (dim, "Residual"), + DataOut < dim > ::type_dof_data, data_component_interpretation); + + Vector subdomain(triangulation.n_active_cells()); + for (unsigned int i = 0; i < subdomain.size(); ++i) + subdomain(i) = triangulation.locally_owned_subdomain(); + data_out.add_data_vector(subdomain, "subdomain"); + + data_out.add_data_vector(cell_constitution, "CellConstitution"); + + data_out.build_patches(); + + const std::string filename = (output_dir + title + "-" + + Utilities::int_to_string(triangulation.locally_owned_subdomain(), + 4)); + + std::ofstream output_vtu((filename + ".vtu").c_str()); + data_out.write_vtu(output_vtu); + pcout << output_dir + title << ".pvtu" << std::endl; + + if (Utilities::MPI::this_mpi_process(mpi_communicator) == 0) { + std::vector filenames; + for (unsigned int i = 0; + i < Utilities::MPI::n_mpi_processes(mpi_communicator); ++i) + filenames.push_back( + title + "-" + Utilities::int_to_string(i, 4) + ".vtu"); + + std::ofstream master_output((output_dir + title + ".pvtu").c_str()); + data_out.write_pvtu_record(master_output, filenames); + } + + TrilinosWrappers::MPI::Vector tmp(solution); + tmp *= -1; + move_mesh(tmp); +} +// @sect4{PlasticityContactProblem::output_for_benchmark} + +template +void PlasticityContactProblem::output_for_benchmark( + const unsigned int cycle) { + Functions::FEFieldFunction, + TrilinosWrappers::MPI::Vector> solution_function(dof_handler, + solution); + std::cout.precision(10); + + Vector solution_p1(dim); + std::vector < Tensor<1, dim> > solution_gradient_p1(dim); + + const Point p1_of_interest(0.5001, 0.5001, 0.9501); + bool point1_found = true; + bool point2_found = true; + + // Calculation of the contact forces + TrilinosWrappers::MPI::Vector lambda(solution); + TrilinosWrappers::MPI::Vector distributed_lambda(system_rhs_newton); + const unsigned int start_res = (resid_vector.local_range().first), end_res = + (resid_vector.local_range().second); + for (unsigned int n = start_res; n < end_res; ++n) + if (constraints.is_inhomogeneously_constrained(n)) + distributed_lambda(n) = resid_vector(n)/diag_mass_matrix_vector(n); + else + distributed_lambda(n) = 0; + distributed_lambda.compress(VectorOperation::insert); + constraints_hanging_nodes.distribute(distributed_lambda); + lambda = distributed_lambda; + Functions::FEFieldFunction, + TrilinosWrappers::MPI::Vector> lambda_function(dof_handler, + lambda); + const Point p2_of_interest(0.49, 0.5001, 1.0); + Vector lambda_p2(dim); + + MPI_Barrier(MPI_COMM_WORLD); + try { + lambda_function.vector_value(p2_of_interest, lambda_p2); + } catch (const typename Functions::FEFieldFunction, + TrilinosWrappers::MPI::Vector>::ExcPointNotAvailableHere &) { + point2_found = false; + } + + if (point2_found == true) { + std::cout << "PoI lambda_z: " << lambda_p2(2) << std::endl; + } + + // Integral of the contact force in z-direction over the whole contact area. + double contact_force = 0.0; + { + QGauss< dim - 1 > face_quadrature_formula(fe.degree + 1); + + FEFaceValues < dim > fe_values_face(fe, face_quadrature_formula, + update_values | update_quadrature_points + | update_JxW_values); + + const unsigned int n_face_q_points = face_quadrature_formula.size(); + + const FEValuesExtractors::Vector displacement(0); + + typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(), endc = dof_handler.end(); + for (; cell != endc; ++cell) + if (cell->is_locally_owned()) + for (unsigned int face = 0; + face < GeometryInfo < dim > ::faces_per_cell; ++face) + if (cell->face(face)->at_boundary() + && cell->face(face)->boundary_indicator() == 1) { + fe_values_face.reinit(cell, face); + + std::vector < Tensor<1, dim> + > lambda_values(n_face_q_points); + fe_values_face[displacement].get_function_values(lambda, + lambda_values); + + for (unsigned int q_point = 0; + q_point < n_face_q_points; ++q_point) + { + contact_force += lambda_values[q_point][2] + * fe_values_face.JxW(q_point); + } + } + contact_force = Utilities::MPI::sum(contact_force, + MPI_COMM_WORLD); + pcout << "Contact force = " << contact_force << std::endl; + } + + // To calculate the contact area between deformable body and obstacle + double contact_area = 0.0; + { + move_mesh(solution); + + QGaussLobatto < dim - 1 > face_quadrature_formula(fe.degree + 1); + + FEFaceValues < dim > fe_values_face(fe, face_quadrature_formula, + update_values | update_quadrature_points + | update_JxW_values); + + const unsigned int dofs_per_face = fe.dofs_per_face; + const unsigned int n_face_q_points = face_quadrature_formula.size(); + + const FEValuesExtractors::Vector displacement(0); + typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(), endc = dof_handler.end(); + for (; cell != endc; ++cell) + if (cell->is_locally_owned()) + for (unsigned int face = 0; + face < GeometryInfo < dim > ::faces_per_cell; ++face){ + if (cell->face(face)->at_boundary() + && cell->face(face)->boundary_indicator() == 1) { + fe_values_face.reinit(cell, face); + + unsigned int contact_counter = 0; + std::vector dof_indices (dofs_per_face); + cell->face(face)->get_dof_indices (dof_indices); + + for (unsigned int q_point=0; q_point - void PlasticityContactProblem::run () - { - use_read_obstacle = false; - if (use_read_obstacle) - { - pcout << "Read the obstacle from a file." << std::endl; - input_obstacle.reset (new Input("obstacle_file.pbm")); - pcout << "Obstacle is available now." << std::endl; - } - - const unsigned int n_cycles = 6; - for (cycle=0; cycle(dof_handler)); - refine_grid (); - computing_timer.exit_section("Setup: refine mesh"); - } +// @sect4{PlasticityContactProblem::run} - setup_system (); +template +void PlasticityContactProblem::run() { - if (cycle > 0) - { - TrilinosWrappers::MPI::Vector distributed_solution (system_rhs_newton); - distributed_solution = solution; - soltrans->interpolate(distributed_solution); - solution = distributed_solution; + if (obstacle_filename!="") + { + pcout << "Read the obstacle from '" << obstacle_filename + << "' ... " << std::flush; + input_obstacle.reset(new Input(obstacle_filename.c_str())); + pcout << "done." << std::endl; } - computing_timer.exit_section("Setup"); - - solve_newton (); - - pcout << " Writing graphical output..." << std::endl; - computing_timer.enter_section("Graphical output"); - - std::ostringstream filename_solution; - filename_solution << "solution-"; - filename_solution << cycle; - output_results (filename_solution.str ()); - - computing_timer.exit_section("Graphical output"); - - computing_timer.print_summary(); - computing_timer.reset(); - } - } + computing_timer.reset(); + for (cycle = 0; cycle < n_cycles; ++cycle) { + { + TimerOutput::Scope t(computing_timer, "Setup"); + + pcout << std::endl; + pcout << "Cycle " << cycle << ':' << std::endl; + + if (cycle == 0) { + make_grid(); + } else { + TimerOutput::Scope t(computing_timer, "Setup: refine mesh"); + if (transfer_solution) + soltrans.reset (new parallel::distributed::SolutionTransfer(dof_handler)); + refine_grid(); + } + + setup_system(); + + if (transfer_solution && cycle > 0) + { + TrilinosWrappers::MPI::Vector distributed_solution( + system_rhs_newton); + distributed_solution = solution; + soltrans->interpolate(distributed_solution); + solution = distributed_solution; + residual_nl_system(solution); + resid_vector = system_rhs_lambda; + resid_vector.compress(VectorOperation::insert); + } + + } + + solve_newton(); + + if (true) //Utilities::MPI::n_mpi_processes(mpi_communicator) <= 64) + { + pcout << " Writing graphical output... " << std::flush; + + TimerOutput::Scope t(computing_timer, "Graphical output"); + + std::ostringstream filename_solution; + filename_solution << "solution-"; + filename_solution << Utilities::int_to_string(cycle, 2); + output_results(filename_solution.str()); + } + + computing_timer.print_summary(); + computing_timer.reset(); + + Utilities::System::MemoryStats stats; + Utilities::System::get_memory_stats(stats); + pcout << "VMPEAK, Resident in kB: " << stats.VmSize << " " + << stats.VmRSS << std::endl; + + if (base_mesh=="box") + output_for_benchmark(cycle); + } +} } // @sect3{The main function} -int main (int argc, char *argv[]) -{ - using namespace dealii; - using namespace Step42; - - deallog.depth_console (0); - - Utilities::MPI::MPI_InitFinalize mpi_initialization (argc, argv); - { - int _n_refinements_global = 3; - - if (argc == 2) - _n_refinements_global = atoi(argv[1]); - - PlasticityContactProblem<3> laplace_problem_3d (_n_refinements_global); - laplace_problem_3d.run (); - } - - return 0; +int main(int argc, char *argv[]) { + using namespace dealii; + using namespace Step42; + + deallog.depth_console(0); + ParameterHandler prm; + PlasticityContactProblem<3>::declare(prm); + if (argc!=2) + { + prm.print_parameters(std::cout, ParameterHandler::Text); + return 0; + } + + prm.read_input(argv[1]); + Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv); + { + PlasticityContactProblem<3> problem(prm); + problem.run(); + } + + return 0; } diff --git a/deal.II/examples/step-43/CMakeLists.txt b/deal.II/examples/step-43/CMakeLists.txt index 96f94caed0..62b492245f 100644 --- a/deal.II/examples/step-43/CMakeLists.txt +++ b/deal.II/examples/step-43/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_TRILINOS) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_TRILINOS = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-43/step-43.cc b/deal.II/examples/step-43/step-43.cc index 0e32b6ef66..2c3477bc36 100644 --- a/deal.II/examples/step-43/step-43.cc +++ b/deal.II/examples/step-43/step-43.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2010 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2010 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Authors: Chih-Che Chueh, University of Victoria, 2010 * Wolfgang Bangerth, Texas A&M University, 2010 */ diff --git a/deal.II/examples/step-44/step-44.cc b/deal.II/examples/step-44/step-44.cc index 18079d1da0..8983261329 100644 --- a/deal.II/examples/step-44/step-44.cc +++ b/deal.II/examples/step-44/step-44.cc @@ -1,19 +1,19 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2010 - 2013 by the deal.II authors and -// & Jean-Paul Pelteret and Andrew McBride -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2010 - 2013 by the deal.II authors and + * & Jean-Paul Pelteret and Andrew McBride + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- /* * Authors: Jean-Paul Pelteret, University of Cape Town, diff --git a/deal.II/examples/step-45/step-45.cc b/deal.II/examples/step-45/step-45.cc index 040d713eb6..301a851e67 100644 --- a/deal.II/examples/step-45/step-45.cc +++ b/deal.II/examples/step-45/step-45.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2010 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2010 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Markus Buerg, University of Karlsruhe, 2010 */ diff --git a/deal.II/examples/step-46/CMakeLists.txt b/deal.II/examples/step-46/CMakeLists.txt index a2c8f5fbc5..02ff830ab7 100644 --- a/deal.II/examples/step-46/CMakeLists.txt +++ b/deal.II/examples/step-46/CMakeLists.txt @@ -33,7 +33,7 @@ IF(NOT DEAL_II_WITH_UMFPACK) MESSAGE(FATAL_ERROR " Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_UMFPACK = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-46/step-46.cc b/deal.II/examples/step-46/step-46.cc index d3fb0d92bb..8ccfd0e64d 100644 --- a/deal.II/examples/step-46/step-46.cc +++ b/deal.II/examples/step-46/step-46.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2011 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2011 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, Texas A&M University, 2011 */ diff --git a/deal.II/examples/step-47/step-47.cc b/deal.II/examples/step-47/step-47.cc index fa212abae8..e607cb2d87 100644 --- a/deal.II/examples/step-47/step-47.cc +++ b/deal.II/examples/step-47/step-47.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2011 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2011 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 2000 */ diff --git a/deal.II/examples/step-48/step-48.cc b/deal.II/examples/step-48/step-48.cc index a37cc84d43..953827c0e0 100644 --- a/deal.II/examples/step-48/step-48.cc +++ b/deal.II/examples/step-48/step-48.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2011 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2011 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Katharina Kormann, Martin Kronbichler, Uppsala University, 2011-2012 */ diff --git a/deal.II/examples/step-49/step-49.cc b/deal.II/examples/step-49/step-49.cc index f3042fd32b..a1139eb765 100644 --- a/deal.II/examples/step-49/step-49.cc +++ b/deal.II/examples/step-49/step-49.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Timo Heister, Texas A&M University, 2013 */ diff --git a/deal.II/examples/step-5/step-5.cc b/deal.II/examples/step-5/step-5.cc index acaa49edd1..f1d146935b 100644 --- a/deal.II/examples/step-5/step-5.cc +++ b/deal.II/examples/step-5/step-5.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 1999 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 1999 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 1999 */ diff --git a/deal.II/examples/step-50/CMakeLists.txt b/deal.II/examples/step-50/CMakeLists.txt index babcd817e0..3a16b1326e 100644 --- a/deal.II/examples/step-50/CMakeLists.txt +++ b/deal.II/examples/step-50/CMakeLists.txt @@ -11,9 +11,6 @@ SET(TARGET_SRC # You can specify additional files here! ) -# A custom command line to run the program -SET(TARGET_RUN mpirun -np 2 ${TARGET}) - # Define the output that should be cleaned: SET(CLEAN_UP_FILES *.vtu *.pvtu *.visit) @@ -43,7 +40,7 @@ Error! The deal.II library found at ${DEAL_II_PATH} was not configured with DEAL_II_WITH_MPI = ON DEAL_II_WITH_P4EST = ON DEAL_II_WITH_TRILINOS = ON -which is required for this tutorial step." +One or all of these are OFF in your installation but are required for this tutorial step." ) ENDIF() diff --git a/deal.II/examples/step-50/step-50.cc b/deal.II/examples/step-50/step-50.cc index b76f929eee..b1398c7362 100644 --- a/deal.II/examples/step-50/step-50.cc +++ b/deal.II/examples/step-50/step-50.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2003 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2003 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Guido Kanschat, University of Heidelberg, 2003 * Baerbel Janssen, University of Heidelberg, 2010 * Wolfgang Bangerth, Texas A&M University, 2010 diff --git a/deal.II/examples/step-51/CMakeLists.txt b/deal.II/examples/step-51/CMakeLists.txt new file mode 100644 index 0000000000..6d7622ff1d --- /dev/null +++ b/deal.II/examples/step-51/CMakeLists.txt @@ -0,0 +1,31 @@ +## +# CMake script for the step-7 tutorial program: +## + +# Set the name of the project and target: +SET(TARGET "step-51") + +# Declare all source files the target consists of: +SET(TARGET_SRC + ${TARGET}.cc + # You can specify additional files here! + ) + +# Usually, you will not need to modify anything beyond this point... + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8) + +FIND_PACKAGE(deal.II 8.0 QUIET + HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR} + ) +IF(NOT ${deal.II_FOUND}) + MESSAGE(FATAL_ERROR "\n" + "*** Could not locate deal.II. ***\n\n" + "You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n" + "or set an environment variable \"DEAL_II_DIR\" that contains this path." + ) +ENDIF() + +DEAL_II_INITIALIZE_CACHED_VARIABLES() +PROJECT(${TARGET}) +DEAL_II_INVOKE_AUTOPILOT() diff --git a/deal.II/examples/step-51/doc/builds-on b/deal.II/examples/step-51/doc/builds-on new file mode 100644 index 0000000000..0946a61258 --- /dev/null +++ b/deal.II/examples/step-51/doc/builds-on @@ -0,0 +1 @@ +step-7 step-32 step-44 diff --git a/deal.II/examples/step-51/doc/intro.dox b/deal.II/examples/step-51/doc/intro.dox new file mode 100644 index 0000000000..d5ecfd4b70 --- /dev/null +++ b/deal.II/examples/step-51/doc/intro.dox @@ -0,0 +1,118 @@ + +

      Introduction

      + +This tutorial program presents the implementation of a hybridizable +discontinuous Galkerin method for the convection-diffusion equation. + +

      Hybridizable discontinuous Galerkin methods

      + +One common argument against the use of discontinuous Galerkin elements +is the large number of globally coupled degrees of freedom that one +must solve in an implicit system. For the FE_DGP_Monomial basis, each +scalar solution component is represented by polynomials of degree p +which yields $(1/dim!)*\prod_{i=1}^{dim}(k+i)$ degrees of freedom per +element. Typically, all degrees of freedom in an element are coupled +to all of the degrees of freedom in the adjacent elements. The resulting +discrete equations yield very large linear systems very quickly, especially +for systems of equations in dim=2 or dim=3. + +To alleviate the computational cost of solving such large linear systems, +the hybridizable discontinuous Galerkin (HDG) methodology has recently been +developed by Cockburn and co-workers +( + N.C. Nguyen and J. Peraire: + Hybridizable discontinuous Galerkin methods for partial differential + equations in continuum mechanics, Journal of Computational Physics, + 2012, 231:18, 5955-5988. + [DOI] +). +The HDG method achieves +this goal by formulating the mathematical problem using Dirichlet-to-Neumann +mappings. The partial differential equations are first written as a first +order system, and each field is then discretized via a DG method. At this +point the single-valued ``trace'' values on the skeleton of the +mesh, i.e. element edges, are taken to be independent unknown quantities. +The Dirichlet-to-Neumann map concept then permits the solution procedure: +
        +
      1. Solve a Dirichlet problem on each element individually, where the local/interior +element solutions no longer couple to neighboring elements. This is known as the +'local solver', and is an embarrissingly parallel element-by-element +solution process. +
      2. Use the local element solutions to construct the global problem for the +trace values. These are the only globally coupled unknowns. +
      3. Modify the local solutions from the computed trace values. +
      + +Another criticism of traditional DG methods is that the approximate fluxes +converge suboptimally. The local HDG solutions can be shown to converge +as $\mathcal{O}(h^{p+1})$. Additionally, a super-convergence property can +be used to post-process a new approximate solution that converges at the +rate $\mathcal{O}(h^{p+2})$. + + + +

      HDG applied to the convection-diffusion problem

      + +The HDG formulation used for this example is taken from +
      + + N.C. Nguyen, J. Peraire, B. Cockburn: + An implicit high-order hybridizable discontinuous Galerkin method + for linear convection–diffusion equations, + Journal of Computational Physics, 2009, 228:9, 3232-3254. + [DOI] + + +We consider the convection-diffusion equation: +@f{eqnarray*} + \nabla \cdot (\mathbf{c} u) - \nabla \cdot (\kappa \nabla u) &=& f, + \quad \text{ in } \Omega, \\ + u &=& g_D, \quad \text{ on } \partial \Omega_D, \\ + (\mathbf{c} u - \kappa \nabla u)\cdot \mathbf{n} &=& g_N, + \quad \text{ on } \partial \Omega_D. +@f} + +Introduce the auxiliary variable $\mathbf{q}=-\kappa \nabla u$ and rewrite +the above equation as the first order system: +@f{eqnarray*} + \mathbf{q} + \kappa \nabla u &=& 0, \quad \text{ in } \Omega, \\ + \nabla \cdot (\mathbf{c} u + \mathbf{q}) &=& f, \quad \text{ in } \Omega, \\ + u &=& g_D, \quad \text{ on } \partial \Omega_D, \\ + (\mathbf{q} + \mathbf{c}u)\cdot\mathbf{n} &=& g_N, + \quad \text{ on } \partial \Omega_D. +@f} + + + +

      Problem specific data

      +Example specific data: +$\Omega := [-1,1]^d$ + +\f[ +\mathbf{c} = \begin{cases} +1, & \textrm{dim}=1 \\ +(y, -x), & \textrm{dim}=2 \\ +(y, -x, 1), & \textrm{dim}=3 +\end{cases} +\f] + +the centers $x_i$ of the exponentials are + $\{x_i\}_1^3 = \{ -\frac{1}{3}, 0, \frac{1}{3} \}$ + $\{\mathbf{x}_i\}_1^3 = \{ (-\frac{1}{2},\frac{1}{2}) + (-\frac{1}{2},-\frac{1}{2}) + (\frac{1}{2},-\frac{1}{2}) + \}$ + $\{\mathbf{x}_i\}_1^3 = \{ (-\frac{1}{2},\frac{1}{2}, \frac{1}{4}) + (-\frac{3}{5},-\frac{1}{2}, -\frac{1}{8}) + (\frac{1}{2},-\frac{1}{2}, \frac{1}{2}) + \}$ + + +

      Implementation

      + +Implementation notes: + +- WorkStream to parallelize local solvers. Workstream is already used in step-32, step-44. +- Reconstructing the trace +- Post-processing the solution for superconvergence +- DataOutFaces: direct output of the global solution \ No newline at end of file diff --git a/deal.II/examples/step-51/doc/kind b/deal.II/examples/step-51/doc/kind new file mode 100644 index 0000000000..c1d9154931 --- /dev/null +++ b/deal.II/examples/step-51/doc/kind @@ -0,0 +1 @@ +techniques diff --git a/deal.II/examples/step-51/doc/results.dox b/deal.II/examples/step-51/doc/results.dox new file mode 100644 index 0000000000..ae6e002753 --- /dev/null +++ b/deal.II/examples/step-51/doc/results.dox @@ -0,0 +1,184 @@ +

      Results

      + + +When the program is run, it outputs information about the respective steps and +convergence tables with errors in the various components in the end. In 2D, +the convergence tables look the following: + +@code +Q1 elements, adaptive refinement: +cells dofs val L2 grad L2 val L2-post + 4 24 6.101e+00 1.065e+01 5.098e+00 + 10 58 3.168e+00 9.223e+00 2.431e+00 + 28 148 2.888e+00 9.368e+00 2.644e+00 + 55 272 6.756e-01 4.088e+00 2.400e-01 + 109 578 2.175e-01 1.529e+00 7.350e-02 + 214 1072 9.783e-02 9.006e-01 2.219e-02 + 409 2056 4.812e-02 5.193e-01 1.081e-02 + 811 3880 2.714e-02 2.971e-01 4.669e-03 + 1555 7204 1.365e-02 1.789e-01 2.627e-03 + 2956 13198 7.919e-03 1.009e-01 1.006e-03 + +Q1 elements, global refinement: +cells dofs val L2 grad L2 val L2-post + 16 80 4.570e+00 - 1.221e+01 - 4.333e+00 - + 36 168 1.869e+00 2.20 7.299e+00 1.27 1.734e+00 2.26 + 64 288 7.177e-01 3.33 4.218e+00 1.91 2.538e-01 6.68 + 144 624 2.729e-01 2.38 1.867e+00 2.01 6.110e-02 3.51 + 256 1088 1.493e-01 2.10 1.046e+00 2.01 2.878e-02 2.62 + 576 2400 6.964e-02 1.88 4.847e-01 1.90 9.202e-03 2.81 + 1024 4224 4.018e-02 1.91 2.785e-01 1.93 4.027e-03 2.87 + 2304 9408 1.831e-02 1.94 1.264e-01 1.95 1.236e-03 2.91 + 4096 16640 1.043e-02 1.96 7.185e-02 1.96 5.306e-04 2.94 + 9216 37248 4.690e-03 1.97 3.228e-02 1.97 1.600e-04 2.96 + +Q3 elements, global refinement: +cells dofs val L2 grad L2 val L2-post + 16 160 2.398e-01 - 1.873e+00 - 1.354e-01 - + 36 336 5.843e-02 3.48 5.075e-01 3.22 1.882e-02 4.87 + 64 576 3.466e-02 1.82 2.534e-01 2.41 4.326e-03 5.11 + 144 1248 8.297e-03 3.53 5.925e-02 3.58 6.330e-04 4.74 + 256 2176 2.254e-03 4.53 1.636e-02 4.47 1.403e-04 5.24 + 576 4800 4.558e-04 3.94 3.278e-03 3.96 1.844e-05 5.01 + 1024 8448 1.471e-04 3.93 1.052e-03 3.95 4.378e-06 5.00 + 2304 18816 2.956e-05 3.96 2.104e-04 3.97 5.751e-07 5.01 + 4096 33280 9.428e-06 3.97 6.697e-05 3.98 1.362e-07 5.01 + 9216 74496 1.876e-06 3.98 1.330e-05 3.99 1.817e-08 4.97 +@endcode + + +One can see the error reduction upon grid refinement, and for the cases where +global refinement was performed, also the convergence rates can be seen. The +quadratic convergence rates of Q1 elements in the $L_2$ norm for both the +scalar variable and the gradient variable can clearly be seen, as is the cubic +rate for the postprocessed scalar variable in the $L_2$ norm. Likewise, the +scalar variable and gradient for Q3 elements converge at fourth order and the +postprocessed scalar variable at fifth order. + +The same convergence rates are observed in 3d. +@code +Q1 elements, adaptive refinement: +cells dofs val L2 grad L2 val L2-post + 8 144 3.846e+00 1.519e+01 2.388e+00 + 29 500 2.800e+00 9.885e+00 1.185e+00 + 113 1792 1.772e+00 9.911e+00 1.423e+00 + 379 5736 6.057e-01 5.011e+00 2.180e-01 + 1317 19412 1.542e-01 1.465e+00 4.176e-02 + 4579 64768 5.059e-02 5.615e-01 9.563e-03 + 14596 199552 2.128e-02 3.124e-01 4.599e-03 + 46180 611380 1.032e-02 1.623e-01 1.643e-03 +144859 1864212 4.996e-03 8.376e-02 6.898e-04 +451053 5684324 2.516e-03 4.559e-02 2.832e-04 + +Q1 elements, global refinement: +cells dofs val L2 grad L2 val L2-post + 8 144 3.846e+00 - 1.519e+01 - 2.388e+00 - + 27 432 4.677e+00 -0.48 2.158e+01 -0.87 3.441e+00 -0.90 + 64 960 2.366e+00 2.37 1.228e+01 1.96 1.831e+00 2.19 + 216 3024 1.225e+00 1.62 8.396e+00 0.94 1.017e+00 1.45 + 512 6912 6.870e-01 2.01 5.314e+00 1.59 2.421e-01 4.99 + 1728 22464 2.912e-01 2.12 2.494e+00 1.87 8.593e-02 2.56 + 4096 52224 1.683e-01 1.91 1.455e+00 1.87 4.056e-02 2.61 + 13824 172800 7.970e-02 1.84 6.866e-01 1.85 1.335e-02 2.74 + 32768 405504 4.637e-02 1.88 3.986e-01 1.89 5.932e-03 2.82 +110592 1354752 2.133e-02 1.92 1.831e-01 1.92 1.851e-03 2.87 + +Q3 elements, global refinement: +cells dofs val L2 grad L2 val L2-post + 8 576 3.845e+00 - 1.742e+01 - 3.550e+00 - + 27 1728 8.915e-01 3.60 6.939e+00 2.27 5.865e-01 4.44 + 64 3840 2.807e-01 4.02 2.713e+00 3.26 1.326e-01 5.17 + 216 12096 7.866e-02 3.14 7.727e-01 3.10 2.112e-02 4.53 + 512 27648 3.640e-02 2.68 3.307e-01 2.95 5.224e-03 4.86 + 1728 89856 8.545e-03 3.57 7.586e-02 3.63 7.642e-04 4.74 + 4096 208896 2.598e-03 4.14 2.314e-02 4.13 1.783e-04 5.06 + 13824 691200 5.314e-04 3.91 4.699e-03 3.93 2.355e-05 4.99 + 32768 1622016 1.723e-04 3.91 1.518e-03 3.93 5.603e-06 4.99 +110592 5419008 3.482e-05 3.94 3.057e-04 3.95 7.375e-07 5.00 +@endcode + + +

      Possibilities for improvements

      + +This tutorial program shows the a basic implementation of an HDG method +without particular focus on a high performance implementation. Let us look at +the computing time of the tutorial program and the share of the individual +components: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        SetupAssembleSolveTrace reconstructPost-processingOutput
       Total timeRelative share
      2D, Q1, cycle 9, 37,248 dofs5.34s0.7%1.2%89.5%0.9%2.3%5.4%
      2D, Q3, cycle 9, 74,496 dofs22.2s0.4%4.3%84.1%4.1%3.5%3.6%
      3D, Q1, cycle 7, 172,800 dofs9.06s3.1%8.9%42.7%7.0%20.6%17.7%
      3D, Q3, cycle 7, 691,200 dofs516s0.6%34.5%13.4%32.8%17.1%1.5%
      + +As can be seen from the table, the solver and assembly calls dominate the +runtime of the program. This also gives a clear indication of where an +improvement makes most sense. + +
        +
      1. Better linear solvers: We use a GMRES iterative solver without + preconditioner, where the number of iteration increases with increasing + problem size (the number of iterations for Q1 elements and global + refinements start at 8 for the small sizes but increase up to 2592 for the + largest size). To do better, one could for example use an algebraic + multigrid preconditioner from Trilinos. For diffusion-dominated problems as + the problem at hand with finer meshes, such a solver can be designed that + uses the matrix-vector products from the more efficient ChunkSparseMatrix on + the finest level, as long as we are not working in parallel with MPI. + +
      2. Speed up assembly by pre-assembling parts that do not change from one + cell to another (those that do neither contain variable coefficients nor + mapping-dependent terms. +
      diff --git a/deal.II/examples/step-51/doc/tooltip b/deal.II/examples/step-51/doc/tooltip new file mode 100644 index 0000000000..784e257e2f --- /dev/null +++ b/deal.II/examples/step-51/doc/tooltip @@ -0,0 +1 @@ +Convection-diffusion equation. Hybridizable discontinuous Galerkin methods. Face elements. diff --git a/deal.II/examples/step-51/step-51.cc b/deal.II/examples/step-51/step-51.cc new file mode 100644 index 0000000000..bc4778c23a --- /dev/null +++ b/deal.II/examples/step-51/step-51.cc @@ -0,0 +1,1223 @@ +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2013 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * + * Author: Martin Kronbichler, Technische Universität München, + * Scott T. Miller, The Pennsylvania State University, 2013 + */ + +// @sect3{Include files} +// +// Most of the deal.II include files have already been covered in previous +// examples are are not commented on. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// However, we do have a few new includes for the example. +// The first one defines finite element spaces on the faces +// of the triangulation, which we refer to as the 'skeleton'. +// These finite elements do not have any support on the element +// interior, and they represent polynomials that have a single +// value on each codimension-1 surface, but admit discontinuities +// on codimension-2 surfaces. +#include + +// The second new file we include defines a new type of sparse matrix. +// The regular SparseMatrix type stores indices to all non-zero entries. +// The ChunkSparseMatrix takes advantage of the coupled nature of +// DG solutions. It stores an index to a matrix sub-block of a specified +// size. In the HDG context, this sub-block-size is actually the number +// of degrees of freedom per face defined by the skeleton solution field. +#include + +// The final new include for this example deals with data output. Since +// we have a finite element field defined on the skeleton of the mesh, +// we would like to visualize what that solution actually is. +// DataOutFaces does exactly this; the interface is the almost the same +// as the familiar DataOut, but the output only has codimension-1 data for +// the simulation. +#include + +using namespace dealii; + +// @sect3{Equation data} +// +// The structure of the analytic solution is the same as in step-7. There +// are two exceptions. Firstly, we also create a solution for the 3d case, +// and secondly, we take into account the convection velocity in the right +// hand side that is variable in this case. +template +class SolutionBase +{ +protected: + static const unsigned int n_source_centers = 3; + static const Point source_centers[n_source_centers]; + static const double width; +}; + + +template <> +const Point<1> +SolutionBase<1>::source_centers[SolutionBase<1>::n_source_centers] += { Point<1>(-1.0 / 3.0), + Point<1>(0.0), + Point<1>(+1.0 / 3.0) +}; + + +template <> +const Point<2> +SolutionBase<2>::source_centers[SolutionBase<2>::n_source_centers] += { Point<2>(-0.5, +0.5), + Point<2>(-0.5, -0.5), + Point<2>(+0.5, -0.5) +}; + +template <> +const Point<3> +SolutionBase<3>::source_centers[SolutionBase<3>::n_source_centers] += { Point<3>(-0.5, +0.5, 0.25), + Point<3>(-0.6, -0.5, -0.125), + Point<3>(+0.5, -0.5, 0.5) }; + +template +const double SolutionBase::width = 1./5.; + + + +template +class ConvectionVelocity : public TensorFunction<1,dim> +{ +public: + ConvectionVelocity() : TensorFunction<1,dim>() {} + + virtual Tensor<1,dim> value (const Point &p) const; +}; + + + +template +Tensor<1,dim> +ConvectionVelocity::value(const Point &p) const +{ + Tensor<1,dim> convection; + switch (dim) + { + case 1: + convection[0] = 1; + break; + case 2: + convection[0] = p[1]; + convection[1] = -p[0]; + break; + case 3: + convection[0] = p[1]; + convection[1] = -p[0]; + convection[2] = 1; + break; + default: + Assert(false, ExcNotImplemented()); + } + return convection; +} + + +template +class Solution : public Function, + protected SolutionBase +{ +public: + Solution () : Function() {} + + virtual double value (const Point &p, + const unsigned int component = 0) const; + + virtual Tensor<1,dim> gradient (const Point &p, + const unsigned int component = 0) const; +}; + + + +template +double Solution::value (const Point &p, + const unsigned int) const +{ + double return_value = 0; + for (unsigned int i=0; in_source_centers; ++i) + { + const Point x_minus_xi = p - this->source_centers[i]; + return_value += std::exp(-x_minus_xi.square() / + (this->width * this->width)); + } + + return return_value / + Utilities::fixed_power(std::sqrt(2. * numbers::PI) * this->width); +} + + + +template +Tensor<1,dim> Solution::gradient (const Point &p, + const unsigned int) const +{ + Tensor<1,dim> return_value; + + for (unsigned int i=0; in_source_centers; ++i) + { + const Point x_minus_xi = p - this->source_centers[i]; + + return_value += (-2 / (this->width * this->width) * + std::exp(-x_minus_xi.square() / + (this->width * this->width)) * + x_minus_xi); + } + + return return_value / Utilities::fixed_power(std::sqrt(2 * numbers::PI) * + this->width); +} + + + +template +class SolutionAndGradient : public Function, + protected SolutionBase +{ +public: + SolutionAndGradient () : Function(dim) {} + + virtual void vector_value (const Point &p, + Vector &v) const + { + AssertDimension(v.size(), dim+1); + Solution solution; + Tensor<1,dim> grad = solution.gradient(p); + for (unsigned int d=0; d +class RightHandSide : public Function, + protected SolutionBase +{ +public: + RightHandSide () : Function() {} + + virtual double value (const Point &p, + const unsigned int component = 0) const; + +private: + const ConvectionVelocity convection_velocity; +}; + + +template +double RightHandSide::value (const Point &p, + const unsigned int) const +{ + Tensor<1,dim> convection = convection_velocity.value(p); + double return_value = 0; + for (unsigned int i=0; in_source_centers; ++i) + { + const Point x_minus_xi = p - this->source_centers[i]; + + return_value += + ((2*dim - 2*convection*x_minus_xi - 4*x_minus_xi.square()/ + (this->width * this->width)) / + (this->width * this->width) * + std::exp(-x_minus_xi.square() / + (this->width * this->width))); + } + + return return_value / Utilities::fixed_power(std::sqrt(2 * numbers::PI) + * this->width); +} + +// @sect3{The Step51 HDG solver class} + +// The HDG solution procedure follows closely that of step-7. The major +// difference is the use of 3 different sets of DoFHandler and FE objects, +// along with the ChunkSparseMatrix and the corresponding solutions vectors. +// We also use WorkStream to enable a multi-threaded local solution process which exploits +// the embarrassingly parallel nature of the local solver. + +template +class Step51 +{ +public: + enum RefinementMode + { + global_refinement, adaptive_refinement + }; + + Step51 (const unsigned int degree, + const RefinementMode refinement_mode); + void run (); + +private: + + struct PerTaskData; + struct ScratchData; + + struct EmptyData; + struct PostProcessScratchData; + void NullFunction(const EmptyData &data); + + void setup_system (); + void assemble_system (const bool reconstruct_trace = false); + void assemble_system_one_cell (const typename DoFHandler::active_cell_iterator &cell, + ScratchData &scratch, + PerTaskData &task_data); + void copy_local_to_global(const PerTaskData &data); + void solve (); + void postprocess (); + void postprocess_one_cell (const typename DoFHandler::active_cell_iterator &cell, + PostProcessScratchData &scratch, + EmptyData &task_data); + void refine_grid (const unsigned int cylce); + void output_results (const unsigned int cycle); + + Triangulation triangulation; + +// The 'local' solutions are interior to each element. These +// represent the primal solution field $u$ as well as the auxiliary +// field $\mathbf{q} = \nabla u$. + FESystem fe_local; + DoFHandler dof_handler_local; + +// The new finite element type and corresponding DoFHandler +// are used for the global solution that couples the element-level local +// solution. + FE_FaceQ fe; + DoFHandler dof_handler; + +// As stated in the introduction, HDG solutions can be post-processed to +// attain superconvegence rates of $\mathcal{O}(h^{p+2})$. +// The post-processed solution is a discontinuous finite element solution +// representing the primal variable on the interior of each cell. +// We define a FE type to represent this post-processed solution, which we +// only use for output after constructing it. + FE_DGQ fe_u_post; + DoFHandler dof_handler_u_post; + +// The degrees of freedom corresponding to the skeleton strongly enforce +// Dirichlet boundary conditions, just as in a continuous Galerkin finite +// element method. We can enforce the boundary conditions in an analogous +// manner through the use of ConstrainMatrix constructs. + ConstraintMatrix constraints; + + // Comment on chunk. + ChunkSparsityPattern sparsity_pattern; + ChunkSparseMatrix system_matrix; + + // Global/skeleton solution/rhs + Vector solution; + Vector system_rhs; + + // Local elementwise solution + Vector solution_local; + + // HDG solutions can be post-processed + // to gain one order of accuracy. + // solution_u_post will be + // our post-processed DG solution on the + // interior of cells represented by a + // DG solution of order (degree+1) + Vector solution_u_post; + + // Same as step-7: + const RefinementMode refinement_mode; + + ConvergenceTable convergence_table; +}; + + + +template +Step51::Step51 (const unsigned int degree, + const RefinementMode refinement_mode) : + fe_local (FE_DGQ(degree), dim, + FE_DGQ(degree), 1), + dof_handler_local (triangulation), + fe (degree), + dof_handler (triangulation), + fe_u_post (degree+1), + dof_handler_u_post (triangulation), + refinement_mode (refinement_mode) +{} + +template +struct Step51::PerTaskData +{ + FullMatrix cell_matrix; + Vector cell_vector; + std::vector dof_indices; + + bool trace_reconstruct; + + PerTaskData(const unsigned int n_dofs, const bool trace_reconstruct) + : cell_matrix(n_dofs, n_dofs), + cell_vector(n_dofs), + dof_indices(n_dofs), + trace_reconstruct(trace_reconstruct) + {} + + void reset(){ + cell_matrix = 0.0; + cell_vector = 0.0; + } +}; + +template +struct Step51::ScratchData +{ + FEValues fe_values_local; + FEFaceValues fe_face_values_local; + FEFaceValues fe_face_values; + + FullMatrix ll_matrix; + FullMatrix lf_matrix; + FullMatrix fl_matrix; + FullMatrix tmp_matrix; + Vector l_rhs; + Vector tmp_rhs; + + std::vector > q_phi; + std::vector q_phi_div; + std::vector u_phi; + std::vector > u_phi_grad; + std::vector tr_phi; + std::vector trace_values; + + std::vector > fe_local_support_on_face; + std::vector > fe_support_on_face; + + ConvectionVelocity convection_velocity; + RightHandSide right_hand_side; + const Solution exact_solution; + + // Full constructor + ScratchData(const FiniteElement &fe, + const FiniteElement &fe_local, + const QGauss &quadrature_formula, + const QGauss &face_quadrature_formula, + const UpdateFlags local_flags, + const UpdateFlags local_face_flags, + const UpdateFlags flags) + : + fe_values_local (fe_local, quadrature_formula, local_flags), + fe_face_values_local (fe_local, face_quadrature_formula, local_face_flags), + fe_face_values (fe, face_quadrature_formula, flags), + ll_matrix (fe_local.dofs_per_cell, fe_local.dofs_per_cell), + lf_matrix (fe_local.dofs_per_cell, fe.dofs_per_cell), + fl_matrix (fe.dofs_per_cell, fe_local.dofs_per_cell), + tmp_matrix (fe.dofs_per_cell, fe_local.dofs_per_cell), + l_rhs (fe_local.dofs_per_cell), + tmp_rhs (fe_local.dofs_per_cell), + q_phi (fe_local.dofs_per_cell), + q_phi_div (fe_local.dofs_per_cell), + u_phi (fe_local.dofs_per_cell), + u_phi_grad (fe_local.dofs_per_cell), + tr_phi (fe.dofs_per_cell), + trace_values(face_quadrature_formula.size()), + fe_local_support_on_face(GeometryInfo::faces_per_cell), + fe_support_on_face(GeometryInfo::faces_per_cell) + { + for (unsigned int face=0; face::faces_per_cell; ++face) + for (unsigned int i=0; i::faces_per_cell; ++face) + for (unsigned int i=0; ireset(), but +// need to have it for the WorkStream interface. + void reset() {} + +}; + +template +struct Step51::EmptyData +{ + EmptyData(){} + void reset(){} +}; + +template +struct Step51::PostProcessScratchData +{ + FEValues fe_values_local; + FEValues fe_values; + + std::vector u_values; + std::vector > u_gradients; + FullMatrix cell_matrix; + + Vector cell_rhs; + Vector cell_sol; + + // Full constructor + PostProcessScratchData(const FiniteElement &fe, + const FiniteElement &fe_local, + const QGauss &quadrature_formula, + const UpdateFlags local_flags, + const UpdateFlags flags) + : + fe_values_local (fe_local, quadrature_formula, local_flags), + fe_values (fe, quadrature_formula, flags), + u_values (quadrature_formula.size()), + u_gradients (quadrature_formula.size()), + cell_matrix (fe.dofs_per_cell, fe.dofs_per_cell), + cell_rhs (fe.dofs_per_cell), + cell_sol (fe.dofs_per_cell) + {} + + // Copy constructor + PostProcessScratchData(const PostProcessScratchData &sd) + : + fe_values_local (sd.fe_values_local.get_fe(), + sd.fe_values_local.get_quadrature(), + sd.fe_values_local.get_update_flags()), + fe_values (sd.fe_values.get_fe(), + sd.fe_values.get_quadrature(), + sd.fe_values.get_update_flags()), + u_values (sd.u_values), + u_gradients (sd.u_gradients), + cell_matrix (sd.cell_matrix), + cell_rhs (sd.cell_rhs), + cell_sol (sd.cell_sol) + {} + + void reset() { + cell_matrix = 0.; + cell_rhs = 0.; + cell_sol = 0.; + } + +}; + +template +void Step51::NullFunction(const EmptyData &data){} + +template +void Step51::copy_local_to_global(const PerTaskData &data) +{ + if(data.trace_reconstruct == false) + constraints.distribute_local_to_global (data.cell_matrix, + data.cell_vector, + data.dof_indices, + system_matrix, system_rhs); +} + +template +void +Step51::setup_system () +{ + dof_handler_local.distribute_dofs(fe_local); + dof_handler.distribute_dofs(fe); + dof_handler_u_post.distribute_dofs(fe_u_post); + + std::cout << " Number of degrees of freedom: " + << dof_handler.n_dofs() + << std::endl; + + solution.reinit (dof_handler.n_dofs()); + system_rhs.reinit (dof_handler.n_dofs()); + + solution_local.reinit (dof_handler_local.n_dofs()); + solution_u_post.reinit (dof_handler_u_post.n_dofs()); + + constraints.clear (); + DoFTools::make_hanging_node_constraints (dof_handler, constraints); + typename FunctionMap::type boundary_functions; + Solution solution_function; + boundary_functions[0] = &solution_function; + VectorTools::project_boundary_values (dof_handler, + boundary_functions, + QGauss(fe.degree+1), + constraints); + constraints.close (); + + { + CompressedSimpleSparsityPattern csp (dof_handler.n_dofs()); + DoFTools::make_sparsity_pattern (dof_handler, csp, + constraints, false); + sparsity_pattern.copy_from(csp, fe.dofs_per_face); + } + system_matrix.reinit (sparsity_pattern); +} + + + +template +void +Step51::assemble_system (const bool trace_reconstruct) +{ + const QGauss quadrature_formula(fe.degree+1); + const QGauss face_quadrature_formula(fe.degree+1); + + const UpdateFlags local_flags (update_values | update_gradients | + update_JxW_values | update_quadrature_points); + + const UpdateFlags local_face_flags (update_values); + + const UpdateFlags flags ( update_values | update_normal_vectors | + update_quadrature_points | + update_JxW_values); + + PerTaskData task_data (fe.dofs_per_cell, + trace_reconstruct); + ScratchData scratch (fe, fe_local, + quadrature_formula, + face_quadrature_formula, + local_flags, + local_face_flags, + flags); + + WorkStream::run(dof_handler.begin_active(), + dof_handler.end(), + *this, + &Step51::assemble_system_one_cell, + &Step51::copy_local_to_global, + scratch, + task_data); +} + + +template +void +Step51::assemble_system_one_cell (const typename DoFHandler::active_cell_iterator &cell, + ScratchData &scratch, + PerTaskData &task_data) +{ + // Construct iterator for dof_handler_local + typename DoFHandler::active_cell_iterator + loc_cell (&triangulation, + cell->level(), + cell->index(), + &dof_handler_local); + + const unsigned int n_q_points = scratch.fe_values_local.get_quadrature().size(); + const unsigned int n_face_q_points = scratch.fe_face_values_local.get_quadrature().size(); + + // const unsigned int dofs_per_cell = scratch.fe_face_values.get_fe().dofs_per_cell; + const unsigned int loc_dofs_per_cell = scratch.fe_values_local.get_fe().dofs_per_cell; + + // Choose stabilization parameter to be 5 * diffusion = 5 + const double tau_stab_diffusion = 5.; + + const FEValuesExtractors::Vector fluxes (0); + const FEValuesExtractors::Scalar scalar (dim); + + scratch.ll_matrix = 0; + scratch.l_rhs = 0; + if (!task_data.trace_reconstruct) + { + scratch.lf_matrix = 0; + scratch.fl_matrix = 0; + task_data.reset(); + } + scratch.fe_values_local.reinit (loc_cell); + + for (unsigned int q=0; q convection + = scratch.convection_velocity.value(scratch.fe_values_local.quadrature_point(q)); + const double JxW = scratch.fe_values_local.JxW(q); + for (unsigned int k=0; k::faces_per_cell; ++face) + { + scratch.fe_face_values_local.reinit(loc_cell, face); + scratch.fe_face_values.reinit(cell, face); + if (task_data.trace_reconstruct) + scratch.fe_face_values.get_function_values (solution, scratch.trace_values); + + for (unsigned int q=0; q normal = scratch.fe_face_values.normal_vector(q); + const Tensor<1,dim> convection + = scratch.convection_velocity.value(scratch.fe_face_values.quadrature_point(q)); + const double tau_stab = (tau_stab_diffusion + + std::abs(convection * normal)); + + for (unsigned int k=0; kface(face)->at_boundary() + && + (cell->face(face)->boundary_indicator() == 1)) + { + const double neumann_value = + scratch.exact_solution.value(scratch.fe_face_values.quadrature_point(q)); + for (unsigned int i=0; iget_dof_indices(task_data.dof_indices); + } + else + { + scratch.ll_matrix.vmult(scratch.tmp_rhs, scratch.l_rhs); + loc_cell->set_dof_values(scratch.tmp_rhs, solution_local); + } +} + + + +template +void Step51::solve () +{ + SolverControl solver_control (system_matrix.m()*10, + 1e-10*system_rhs.l2_norm()); + SolverGMRES<> solver (solver_control, 50); + solver.solve (system_matrix, solution, system_rhs, + PreconditionIdentity()); + + std::cout << " Number of GMRES iterations: " << solver_control.last_step() + << std::endl; + + system_matrix.clear(); + sparsity_pattern.reinit(0,0,0,1); + + constraints.distribute(solution); + + // update local values + assemble_system(true); +} + + + +template +void +Step51::postprocess() +{ + // construct post-processed solution with (hopefully) higher order of + // accuracy + { + const QGauss quadrature_formula(fe_u_post.degree+1); + const UpdateFlags local_flags (update_values); + const UpdateFlags flags ( update_values | update_gradients | + update_JxW_values); + + EmptyData task_data; + + PostProcessScratchData scratch (fe_u_post, fe_local, + quadrature_formula, + local_flags, + flags); + + WorkStream::run(dof_handler_u_post.begin_active(), + dof_handler_u_post.end(), + *this, + &Step51::postprocess_one_cell, + &Step51::NullFunction, + scratch, + task_data); + } + +// Compute some convergence rates, etc., and add to a table + Vector difference_per_cell (triangulation.n_active_cells()); + + ComponentSelectFunction value_select (dim, dim+1); + VectorTools::integrate_difference (dof_handler_local, + solution_local, + SolutionAndGradient(), + difference_per_cell, + QGauss(fe.degree+2), + VectorTools::L2_norm, + &value_select); + const double L2_error = difference_per_cell.l2_norm(); + + ComponentSelectFunction gradient_select (std::pair(0, dim), + dim+1); + VectorTools::integrate_difference (dof_handler_local, + solution_local, + SolutionAndGradient(), + difference_per_cell, + QGauss(fe.degree+2), + VectorTools::L2_norm, + &gradient_select); + const double grad_error = difference_per_cell.l2_norm(); + + VectorTools::integrate_difference (dof_handler_u_post, + solution_u_post, + Solution(), + difference_per_cell, + QGauss(fe.degree+3), + VectorTools::L2_norm); + const double post_error = difference_per_cell.l2_norm(); + + convergence_table.add_value("cells", triangulation.n_active_cells()); + convergence_table.add_value("dofs", dof_handler.n_dofs()); + convergence_table.add_value("val L2", L2_error); + convergence_table.add_value("grad L2", grad_error); + convergence_table.add_value("val L2-post", post_error); +} + +template +void +Step51::postprocess_one_cell (const typename DoFHandler::active_cell_iterator &cell, + PostProcessScratchData &scratch, + EmptyData &task_data) +{ + scratch.reset(); + + typename DoFHandler::active_cell_iterator + loc_cell (&triangulation, + cell->level(), + cell->index(), + &dof_handler_local); + + scratch.fe_values_local.reinit (loc_cell); + scratch.fe_values.reinit(cell); + + FEValuesExtractors::Vector fluxes(0); + FEValuesExtractors::Scalar scalar(dim); + + const unsigned int n_q_points = scratch.fe_values.get_quadrature().size(); + const unsigned int dofs_per_cell = scratch.fe_values.dofs_per_cell; + + scratch.fe_values_local[scalar].get_function_values(solution_local, scratch.u_values); + scratch.fe_values_local[fluxes].get_function_values(solution_local, scratch.u_gradients); + + double sum = 0; + for (unsigned int i=1; idistribute_local_to_global(scratch.cell_sol, solution_u_post); +} + + +template +void Step51::output_results (const unsigned int cycle) +{ + std::string filename; + switch (refinement_mode) + { + case global_refinement: + filename = "solution-global"; + break; + case adaptive_refinement: + filename = "solution-adaptive"; + break; + default: + Assert (false, ExcNotImplemented()); + } + + std::string face_out(filename); + face_out += "-face"; + + filename += "-q" + Utilities::int_to_string(fe.degree,1); + filename += "-" + Utilities::int_to_string(cycle,2); + filename += ".vtk"; + std::ofstream output (filename.c_str()); + + DataOut data_out; + std::vector names (dim, "gradient"); + names.push_back ("solution"); + std::vector + component_interpretation + (dim+1, DataComponentInterpretation::component_is_part_of_vector); + component_interpretation[dim] + = DataComponentInterpretation::component_is_scalar; + data_out.add_data_vector (dof_handler_local, solution_local, + names, component_interpretation); + + // Post-processed solution: can now add more than 1 dof_handler to + // the DataOut object! + std::vector post_name(1,"u_post"); + std::vector + post_comp_type(1, DataComponentInterpretation::component_is_scalar); + data_out.add_data_vector (dof_handler_u_post, solution_u_post, + post_name, post_comp_type); + + data_out.build_patches (fe.degree); + data_out.write_vtk (output); + + face_out += "-q" + Utilities::int_to_string(fe.degree,1); + face_out += "-" + Utilities::int_to_string(cycle,2); + face_out += ".vtk"; + std::ofstream face_output (face_out.c_str()); + + DataOutFaces data_out_face(false); + std::vector face_name(1,"lambda"); + std::vector + face_component_type(1, DataComponentInterpretation::component_is_scalar); + + data_out_face.add_data_vector (dof_handler, + solution, + face_name, + face_component_type); + + data_out_face.build_patches (fe.degree); + data_out_face.write_vtk (face_output); +} + + + +template +void Step51::refine_grid (const unsigned int cycle) +{ + if (cycle == 0) + { + GridGenerator::subdivided_hyper_cube (triangulation, 2, -1, 1); + } + else + switch (refinement_mode) + { + case global_refinement: + { + triangulation.clear(); + GridGenerator::subdivided_hyper_cube (triangulation, 2+(cycle%2), -1, 1); + triangulation.refine_global(3-dim+cycle/2); + break; + } + + case adaptive_refinement: + { + Vector estimated_error_per_cell (triangulation.n_active_cells()); + + FEValuesExtractors::Scalar scalar(dim); + typename FunctionMap::type neumann_boundary; + KellyErrorEstimator::estimate (dof_handler_local, + QGauss(3), + neumann_boundary, + solution_local, + estimated_error_per_cell, + fe_local.component_mask(scalar)); + + GridRefinement::refine_and_coarsen_fixed_number (triangulation, + estimated_error_per_cell, + 0.3, 0.); + + triangulation.execute_coarsening_and_refinement (); + + break; + } + + default: + { + Assert (false, ExcNotImplemented()); + } + } + } + + + + + +template +void Step51::run () +{ + for (unsigned int cycle=0; cycle<10; ++cycle) + { + std::cout << "Cycle " << cycle << ':' << std::endl; + + refine_grid (cycle); + setup_system (); + assemble_system (false); + solve (); + postprocess(); + output_results (cycle); + } + + + + convergence_table.set_precision("val L2", 3); + convergence_table.set_scientific("val L2", true); + convergence_table.set_precision("grad L2", 3); + convergence_table.set_scientific("grad L2", true); + convergence_table.set_precision("val L2-post", 3); + convergence_table.set_scientific("val L2-post", true); + + if (refinement_mode == global_refinement) + { + convergence_table + .evaluate_convergence_rates("val L2", "cells", ConvergenceTable::reduction_rate_log2, dim); + convergence_table + .evaluate_convergence_rates("grad L2", "cells", ConvergenceTable::reduction_rate_log2, dim); + convergence_table + .evaluate_convergence_rates("val L2-post", "cells", ConvergenceTable::reduction_rate_log2, dim); + } + convergence_table.write_text(std::cout); +} + + +int main (int argc, char** argv) +{ + const unsigned int dim = 2; + + try + { + using namespace dealii; + + deallog.depth_console (0); + + // Now for the three calls to the main class in complete analogy to + // step-7. + { + std::cout << "Solving with Q1 elements, adaptive refinement" << std::endl + << "=============================================" << std::endl + << std::endl; + + Step51 hdg_problem (1, Step51::adaptive_refinement); + hdg_problem.run (); + + std::cout << std::endl; + } + + { + std::cout << "Solving with Q1 elements, global refinement" << std::endl + << "===========================================" << std::endl + << std::endl; + + Step51 hdg_problem (1, Step51::global_refinement); + hdg_problem.run (); + + std::cout << std::endl; + } + + { + std::cout << "Solving with Q3 elements, global refinement" << std::endl + << "===========================================" << std::endl + << std::endl; + + Step51 hdg_problem (3, Step51::global_refinement); + hdg_problem.run (); + + std::cout << std::endl; + } + + } + catch (std::exception &exc) + { + std::cerr << std::endl << std::endl + << "----------------------------------------------------" + << std::endl; + std::cerr << "Exception on processing: " << std::endl + << exc.what() << std::endl + << "Aborting!" << std::endl + << "----------------------------------------------------" + << std::endl; + return 1; + } + catch (...) + { + std::cerr << std::endl << std::endl + << "----------------------------------------------------" + << std::endl; + std::cerr << "Unknown exception!" << std::endl + << "Aborting!" << std::endl + << "----------------------------------------------------" + << std::endl; + return 1; + } + + return 0; +} diff --git a/deal.II/examples/step-6/step-6.cc b/deal.II/examples/step-6/step-6.cc index ea45447cb6..681b9e4a34 100644 --- a/deal.II/examples/step-6/step-6.cc +++ b/deal.II/examples/step-6/step-6.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2000 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2000 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 2000 */ diff --git a/deal.II/examples/step-7/step-7.cc b/deal.II/examples/step-7/step-7.cc index ff5a243964..058e7cf1cd 100644 --- a/deal.II/examples/step-7/step-7.cc +++ b/deal.II/examples/step-7/step-7.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2000 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2000 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth and Ralf Hartmann, University of Heidelberg, 2000 */ @@ -950,7 +950,7 @@ namespace Step7 // // For this, we will use the following convention: Faces belonging to Gamma1 // will have the boundary indicator 0 (which is the default, so - // we don't have to set it explicitely), and faces belonging to Gamma2 will + // we don't have to set it explicitly), and faces belonging to Gamma2 will // use 1 as boundary indicator. To set these values, we loop // over all cells, then over all faces of a given cell, check whether it is // part of the boundary that we want to denote by Gamma2, and if so set its diff --git a/deal.II/examples/step-8/step-8.cc b/deal.II/examples/step-8/step-8.cc index b63fa0db1a..da7eccfd57 100644 --- a/deal.II/examples/step-8/step-8.cc +++ b/deal.II/examples/step-8/step-8.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2000 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2000 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 2000 */ diff --git a/deal.II/examples/step-9/step-9.cc b/deal.II/examples/step-9/step-9.cc index 26df070fef..9f6883e273 100644 --- a/deal.II/examples/step-9/step-9.cc +++ b/deal.II/examples/step-9/step-9.cc @@ -1,20 +1,20 @@ -// --------------------------------------------------------------------- -// $Id$ -// -// Copyright (C) 2000 - 2013 by the deal.II authors -// -// This file is part of the deal.II library. -// -// The deal.II library is free software; you can use it, redistribute -// 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. -// The full text of the license can be found in the file LICENSE at -// the top level of the deal.II distribution. -// -// --------------------------------------------------------------------- - -/* +/* --------------------------------------------------------------------- + * $Id$ + * + * Copyright (C) 2000 - 2013 by the deal.II authors + * + * This file is part of the deal.II library. + * + * The deal.II library is free software; you can use it, redistribute + * 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. + * The full text of the license can be found in the file LICENSE at + * the top level of the deal.II distribution. + * + * --------------------------------------------------------------------- + + * * Author: Wolfgang Bangerth, University of Heidelberg, 2000 */ diff --git a/deal.II/include/deal.II/base/config.h.in b/deal.II/include/deal.II/base/config.h.in index 43d4365906..ca90c59df9 100644 --- a/deal.II/include/deal.II/base/config.h.in +++ b/deal.II/include/deal.II/base/config.h.in @@ -1,14 +1,18 @@ -//---------------------------- config.h.in --------------------------- -// $Id$ -// Version: $Name$ +// --------------------------------------------------------------------- +// $Id$ // -// Copyright (C) 2012, 2013 by the deal.II authors +// Copyright (C) 2012 - 2013 by the deal.II authors // -// TODO: Header +// This file is part of the deal.II library. // -// Author: Matthias Maier +// The deal.II library is free software; you can use it, redistribute +// 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. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. // -//---------------------------- config.h.in --------------------------- +// --------------------------------------------------------------------- #ifndef __deal2__config_h #define __deal2__config_h @@ -184,12 +188,6 @@ * Configured in check_2_compiler_bugs: * ****************************************/ -/* Defined if we have to work around a bug where the compiler doesn't accept - * an explicit destructor call. See the aclocal.m4 file in the top-level - * directory for a description of this bug. - */ -#cmakedefine DEAL_II_EXPLICIT_DESTRUCTOR_BUG - /* Defined if we have to work around a bug with some compilers that will not * allow us to specify a fully specialized class of a template as a friend. * See the aclocal.m4 file in the top-level directory for a description of diff --git a/deal.II/include/deal.II/base/data_out_base.h b/deal.II/include/deal.II/base/data_out_base.h index b054a3a822..43e7e9a294 100644 --- a/deal.II/include/deal.II/base/data_out_base.h +++ b/deal.II/include/deal.II/base/data_out_base.h @@ -1222,11 +1222,21 @@ public: */ unsigned int cycle; + /** + * Flag to determine whether the current + * date and time shall be printed as a comment + * in the file's second line. + * + * Default is true. + */ + bool print_date_and_time; + /** * Default constructor. */ - VtkFlags (const double time = std::numeric_limits::min(), - const unsigned int cycle = std::numeric_limits::min()); + VtkFlags (const double time = std::numeric_limits::min(), + const unsigned int cycle = std::numeric_limits::min(), + const bool print_date_and_time = true); /** * Declare the flags with name @@ -1848,7 +1858,8 @@ public: * DataOutInterface::write_vtu_footer() and DataOutInterface::write_vtu_main() * by DataOutBase::write_vtu(). */ - static void write_vtu_header (std::ostream &out); + static void write_vtu_header (std::ostream &out, + const VtkFlags &flags); /** * This writes the footer for the xml based vtu file format. This diff --git a/deal.II/include/deal.II/base/derivative_form.h b/deal.II/include/deal.II/base/derivative_form.h index 313c343759..87ef8c844d 100644 --- a/deal.II/include/deal.II/base/derivative_form.h +++ b/deal.II/include/deal.II/base/derivative_form.h @@ -35,11 +35,8 @@ DEAL_II_NAMESPACE_OPEN In deal.II we represent these derivaties using objects of type DerivativeForm<1,dim,spacedim>, DerivativeForm<2,dim,spacedim> and so on. - @author Sebastian Pauletti, 2011 - */ - template class DerivativeForm { diff --git a/deal.II/include/deal.II/base/geometry_info.h b/deal.II/include/deal.II/base/geometry_info.h index 4704ebfdf6..22bfb276d2 100644 --- a/deal.II/include/deal.II/base/geometry_info.h +++ b/deal.II/include/deal.II/base/geometry_info.h @@ -2173,8 +2173,7 @@ struct GeometryInfo void alternating_form_at_vertices (const Point (&vertices)[vertices_per_cell], - Tensor (&forms)[vertices_per_cell]) - ; + Tensor (&forms)[vertices_per_cell]); /** * For each face of the reference diff --git a/deal.II/include/deal.II/base/partitioner.h b/deal.II/include/deal.II/base/partitioner.h index 977f40a321..9f573a98b6 100644 --- a/deal.II/include/deal.II/base/partitioner.h +++ b/deal.II/include/deal.II/base/partitioner.h @@ -49,12 +49,12 @@ namespace Utilities * where other processors might require information from. In a * sense, these import indices form the dual of the ghost * indices. This information is gathered once when constructing the - * partitioner, which obviates subsequent global communcation steps + * partitioner, which obviates subsequent global communication steps * when exchanging data. * - * The partitioner includes a mechanism for converting global to - * local and local to global indices. The storage convention for the - * partitioner is as follows. The local range is associated with + * The partitioner includes a mechanism for converting global to local and + * local to global indices. Internally, this class stores vector elements + * using the convention as follows: The local range is associated with * local indices [0,@p local_size), and ghost indices are stored * consecutively in [@p local_size, @p local_size + @p * n_ghost_indices). The ghost indices are sorted according to their diff --git a/deal.II/include/deal.II/base/subscriptor.h b/deal.II/include/deal.II/base/subscriptor.h index a6372e016e..44d425865c 100644 --- a/deal.II/include/deal.II/base/subscriptor.h +++ b/deal.II/include/deal.II/base/subscriptor.h @@ -49,7 +49,7 @@ DEAL_II_NAMESPACE_OPEN * same. The handling in SmartPointer will take care of this. * * @note Due to a problem with volatile declarations, this - * additional feature is switched of if multithreading is used. + * additional feature is switched off if multithreading is used. * * @ingroup memory * @author Guido Kanschat, 1998 - 2005 diff --git a/deal.II/include/deal.II/base/symmetric_tensor.h b/deal.II/include/deal.II/base/symmetric_tensor.h index dd79b821d5..93ffc6296a 100644 --- a/deal.II/include/deal.II/base/symmetric_tensor.h +++ b/deal.II/include/deal.II/base/symmetric_tensor.h @@ -797,8 +797,8 @@ public: * one. * * If the present object is a - * rank-4 tensor, the the result - * is a rank-2 tensor, the + * rank-4 tensor, then the result + * is a rank-2 tensor, i.e., the * operation contracts over the * last two indices of the * present object and the indices @@ -2842,8 +2842,68 @@ operator / (const SymmetricTensor &t, return tt; } +/** + * Compute the scalar product $a:b=\sum_{i,j} a_{ij}b_{ij}$ between two + * tensors $a,b$ of rank 2. In the current case where both arguments are + * symmetric tensors, this is equivalent to calling the expression + * t1*t2 which uses the overloaded operator* + * between two symmetric tensors of rank 2. + * + * @relates SymmetricTensor + */ +template +inline +Number +scalar_product (const SymmetricTensor<2,dim,Number> &t1, + const SymmetricTensor<2,dim,Number> &t2) +{ + return (t1*t2); +} + + +/** + * Compute the scalar product $a:b=\sum_{i,j} a_{ij}b_{ij}$ between two + * tensors $a,b$ of rank 2. We don't use operator* for this + * operation since the product between two tensors is usually assumed to be + * the contraction over the last index of the first tensor and the first index + * of the second tensor, for example $(a\cdot b)_{ij}=\sum_k a_{ik}b_{kj}$. + * + * @relates Tensor + * @relates SymmetricTensor + */ +template +inline +Number +scalar_product (const SymmetricTensor<2,dim,Number> &t1, + const Tensor<2,dim,Number> &t2) +{ + Number s = 0; + for (unsigned int i=0; ioperator* for this + * operation since the product between two tensors is usually assumed to be + * the contraction over the last index of the first tensor and the first index + * of the second tensor, for example $(a\cdot b)_{ij}=\sum_k a_{ik}b_{kj}$. + * + * @relates Tensor + * @relates SymmetricTensor + */ +template +inline +Number +scalar_product (const Tensor<2,dim,Number> &t1, + const SymmetricTensor<2,dim,Number> &t2) +{ + return scalar_product(t2, t1); +} + /** * Double contraction between a rank-4 and a rank-2 symmetric tensor, diff --git a/deal.II/include/deal.II/base/table_handler.h b/deal.II/include/deal.II/base/table_handler.h index 0e2aebf0fe..314a83a7b9 100644 --- a/deal.II/include/deal.II/base/table_handler.h +++ b/deal.II/include/deal.II/base/table_handler.h @@ -311,13 +311,23 @@ public: * 2 13 a * 1 0 "" * @endcode - * - **/ + * - org_mode_table: Outputs to org-mode (http://orgmode.org/) table + * format. It is easy to convert org-mode tables to HTML/LaTeX/csv. + * Example output: + * @code + * | key1 | key2 | key3 | + * | 0 | 0 | "" | + * | 1 | 0 | "" | + * | 2 | 13 | a | + * | 1 | 0 | "" | + * @endcode + */ enum TextOutputFormat { table_with_headers, table_with_separate_column_description, - simple_table_with_separate_column_description + simple_table_with_separate_column_description, + org_mode_table }; /** diff --git a/deal.II/include/deal.II/base/template_constraints.h b/deal.II/include/deal.II/base/template_constraints.h index f77a552c71..b123fbe109 100644 --- a/deal.II/include/deal.II/base/template_constraints.h +++ b/deal.II/include/deal.II/base/template_constraints.h @@ -209,7 +209,7 @@ namespace internal * template <> * void X::f<0> () { ...operate on the vertices of a cell... } * - * template void f(X &x) { + * template void g(X &x) { * x.f (); * } * @endcode @@ -238,7 +238,7 @@ namespace internal * template * void X::f (int2type<1>) { ...operate on the lines of a cell... } * - * template void f(X &x) { + * template void g(X &x) { * x.f (int2type()); * } * @endcode diff --git a/deal.II/include/deal.II/base/tensor_function.h b/deal.II/include/deal.II/base/tensor_function.h index aab8d60113..c6da7af3aa 100644 --- a/deal.II/include/deal.II/base/tensor_function.h +++ b/deal.II/include/deal.II/base/tensor_function.h @@ -123,7 +123,7 @@ public: -/* +/** * Provide a tensor valued function which always returns a constant tensor * value. Obviously, all derivates of this function are zero. * @@ -162,7 +162,7 @@ private: -/* +/** * Provide a tensor valued function which always returns zero. * Obviously, all derivates of this function are zero. * diff --git a/deal.II/include/deal.II/base/utilities.h b/deal.II/include/deal.II/base/utilities.h index df17f8f976..db5d8b435a 100644 --- a/deal.II/include/deal.II/base/utilities.h +++ b/deal.II/include/deal.II/base/utilities.h @@ -226,7 +226,7 @@ namespace Utilities * templates. * * Use this class as in - * fixed_int_power@<5,2@>::value + * fixed_int_power@<5,2@>::%value * to compute 52. */ template diff --git a/deal.II/include/deal.II/dofs/dof_handler.h b/deal.II/include/deal.II/dofs/dof_handler.h index 9e990e154e..93d765a670 100644 --- a/deal.II/include/deal.II/dofs/dof_handler.h +++ b/deal.II/include/deal.II/dofs/dof_handler.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/deal.II/include/deal.II/fe/fe.h b/deal.II/include/deal.II/fe/fe.h index 8d52d8c943..31fb8c8cb7 100644 --- a/deal.II/include/deal.II/fe/fe.h +++ b/deal.II/include/deal.II/fe/fe.h @@ -924,6 +924,65 @@ public: std::pair face_system_to_component_index (const unsigned int index) const; + /** + * Given an index in the natural ordering of indices on a face, return the + * index of the same degree of freedom on the cell. + * + * To explain the concept, consider the case where we would like to know + * whether a degree of freedom on a face, for example as part of an FESystem + * element, is primitive. Unfortunately, the + * is_primitive() function in the FiniteElement class takes a cell index, so + * we would need to find the cell index of the shape function that + * corresponds to the present face index. This function does that. + * + * Code implementing this would then look like this: + * @code + * for (i=0; i::conforms (const Conformity space) const } - -template <> -inline -unsigned int -FiniteElementData<1>:: -face_to_equivalent_cell_index (const unsigned int index) const -{ - Assert (index < dofs_per_face, - ExcIndexRange (index, 0, dofs_per_face)); - return index; -} - - - -template <> -inline -unsigned int -FiniteElementData<2>:: -face_to_equivalent_cell_index (const unsigned int index) const -{ - Assert (index < dofs_per_face, - ExcIndexRange (index, 0, dofs_per_face)); - - // on face 0, the vertices are 0 and 2 - if (index < this->dofs_per_vertex) - return index; - else if (index < 2*this->dofs_per_vertex) - return index + this->dofs_per_vertex; - else - // this is a dof on line 0, so on the cell there are now 4 vertices - // instead of only 2 ahead of this one - return index + 2*this->dofs_per_vertex; -} - - - - -template <> -inline -unsigned int -FiniteElementData<3>:: -face_to_equivalent_cell_index (const unsigned int index) const -{ - // this case is just way too complicated. fall back to face_to_cell_index - return face_to_cell_index(index, 0, true); -} - #endif // DOXYGEN diff --git a/deal.II/include/deal.II/fe/fe_face.h b/deal.II/include/deal.II/fe/fe_face.h index a091042adb..3047f7a06a 100644 --- a/deal.II/include/deal.II/fe/fe_face.h +++ b/deal.II/include/deal.II/fe/fe_face.h @@ -25,9 +25,12 @@ DEAL_II_NAMESPACE_OPEN /** - * A finite element, which is a tensor product polynomial on each face - * and undefined in the interior of the cells. The basis functions on - * the faces are from Polynomials::LagrangeEquidistant + * A finite element, which is a tensor product polynomial on each face and + * undefined in the interior of the cells. The basis functions on the faces + * are Lagrange polynomials based on the support points of the + * (dim-1)-dimensional Gauss--Lobatto quadrature rule. For element degree one + * and two, the polynomials hence correspond to the usual Lagrange polynomials + * on equidistant points. * * This finite element is the trace space of FE_RaviartThomas on the * faces and serves in hybridized methods. @@ -39,13 +42,9 @@ DEAL_II_NAMESPACE_OPEN * element space, but all shape function values extracted will equal * to zero. * - * @todo Polynomials::LagrangeEquidistant should be and will be - * replaced by Polynomials::LagrangeGaussLobatto as soon as such a - * polynomial set exists. - * * @ingroup fe - * @author Guido Kanschat - * @date 2009, 2011 + * @author Guido Kanschat, Martin Kronbichler + * @date 2009, 2011, 2013 */ template class FE_FaceQ : public FE_PolyFace, dim, spacedim> @@ -67,6 +66,31 @@ public: */ virtual std::string get_name () const; + /** + * Return the matrix interpolating from a face of of one element to the face + * of the neighboring element. The size of the matrix is then + * source.dofs_per_face times this->dofs_per_face. This + * element only provides interpolation matrices for elements of the same + * type and FE_Nothing. For all other elements, an exception of type + * FiniteElement::ExcInterpolationNotImplemented is thrown. + */ + virtual void + get_face_interpolation_matrix (const FiniteElement &source, + FullMatrix &matrix) const; + + /** + * Return the matrix interpolating from a face of of one element to the face + * of the neighboring element. The size of the matrix is then + * source.dofs_per_face times this->dofs_per_face. This + * element only provides interpolation matrices for elements of the same + * type and FE_Nothing. For all other elements, an exception of type + * FiniteElement::ExcInterpolationNotImplemented is thrown. + */ + virtual void + get_subface_interpolation_matrix (const FiniteElement &source, + const unsigned int subface, + FullMatrix &matrix) const; + /** * Check for non-zero values on a face. * @@ -78,6 +102,28 @@ public: virtual bool has_support_on_face (const unsigned int shape_index, const unsigned int face_index) const; + /** + * Return whether this element implements its hanging node constraints in + * the new way, which has to be used to make elements "hp compatible". + * + * For the FE_Q class the result is always true (independent of the degree + * of the element), as it implements the complete set of functions necessary + * for hp capability. + */ + virtual bool hp_constraints_are_implemented () const; + + /** + * Return whether this element dominates the one given as argument when they + * meet at a common face, whether it is the other way around, whether + * neither dominates, or if either could dominate. + * + * For a definition of domination, see FiniteElementBase::Domination and in + * particular the @ref hp_paper "hp paper". + */ + virtual + FiniteElementDomination::Domination + compare_for_face_domination (const FiniteElement &fe_other) const; + private: /** * Return vector with dofs per vertex, line, quad, hex. diff --git a/deal.II/include/deal.II/fe/fe_q_base.h b/deal.II/include/deal.II/fe/fe_q_base.h index 6f17bd38a4..15b6701171 100644 --- a/deal.II/include/deal.II/fe/fe_q_base.h +++ b/deal.II/include/deal.II/fe/fe_q_base.h @@ -62,13 +62,11 @@ public: /** * Return the matrix interpolating from a face of of one element to the face * of the neighboring element. The size of the matrix is then - * source.dofs_per_face times this->dofs_per_face. - * - * Derived elements will have to implement this function. They may only - * provide interpolation matrices for certain source finite elements, for - * example those from the same family. If they don't implement interpolation - * from a given element, then they must throw an exception of type - * FiniteElement::ExcInterpolationNotImplemented. + * source.dofs_per_face times this->dofs_per_face. The + * FE_Q element family only provides interpolation matrices for elements of + * the same type and FE_Nothing. For all other elements, an exception of + * type FiniteElement::ExcInterpolationNotImplemented is + * thrown. */ virtual void get_face_interpolation_matrix (const FiniteElement &source, @@ -77,13 +75,11 @@ public: /** * Return the matrix interpolating from a face of of one element to the face * of the neighboring element. The size of the matrix is then - * source.dofs_per_face times this->dofs_per_face. - * - * Derived elements will have to implement this function. They may only - * provide interpolation matrices for certain source finite elements, for - * example those from the same family. If they don't implement interpolation - * from a given element, then they must throw an exception of type - * FiniteElement::ExcInterpolationNotImplemented. + * source.dofs_per_face times this->dofs_per_face. The + * FE_Q element family only provides interpolation matrices for elements of + * the same type and FE_Nothing. For all other elements, an exception of + * type FiniteElement::ExcInterpolationNotImplemented is + * thrown. */ virtual void get_subface_interpolation_matrix (const FiniteElement &source, @@ -157,6 +153,48 @@ public: get_prolongation_matrix (const unsigned int child, const RefinementCase &refinement_case=RefinementCase::isotropic_refinement) const; + /** + * Given an index in the natural ordering of indices on a face, return the + * index of the same degree of freedom on the cell. + * + * To explain the concept, consider the case where we would like to know + * whether a degree of freedom on a face, for example as part of an FESystem + * element, is primitive. Unfortunately, the + * is_primitive() function in the FiniteElement class takes a cell index, so + * we would need to find the cell index of the shape function that + * corresponds to the present face index. This function does that. + * + * Code implementing this would then look like this: + * @code + * for (i=0; i &refinement_case=RefinementCase::isotropic_refinement) const; + /** + * Given an index in the natural ordering of indices on a face, return the + * index of the same degree of freedom on the cell. + * + * To explain the concept, consider the case where we would like to know + * whether a degree of freedom on a face, for example as part of an FESystem + * element, is primitive. Unfortunately, the + * is_primitive() function in the FiniteElement class takes a cell index, so + * we would need to find the cell index of the shape function that + * corresponds to the present face index. This function does that. + * + * Code implementing this would then look like this: + * @code + * for (i=0; i class FESubfaceValues; * the transform() functions of * inheriting classes in order to * work. + * + * @ingroup mapping */ enum MappingType { diff --git a/deal.II/include/deal.II/grid/grid_generator.h b/deal.II/include/deal.II/grid/grid_generator.h index 3967669860..a3f4021278 100644 --- a/deal.II/include/deal.II/grid/grid_generator.h +++ b/deal.II/include/deal.II/grid/grid_generator.h @@ -33,34 +33,25 @@ template class SparseMatrix; /** - * This class provides a collection of functions for generating basic - * triangulations. Below, we try to provide some pictures in order to - * illustrate at least the more complex ones. + * This namespace provides a collection of functions for generating + * triangulations for some basic geometries. * * Some of these functions receive a flag @p colorize. If this is - * set, parts of the boundary receive different boundary numbers, - * allowing them to be distinguished by application programs. See the - * documentation of the functions for details. - * - * Additionally this class provides a function - * (@p laplace_transformation) that smoothly transforms a grid - * according to given new boundary points. This can be used to - * transform (simple-shaped) grids to a more complicated ones, like a - * shell onto a grid of an airfoil, for example. - * - * No meshes for the codimension one case are provided at the moment. + * set, parts of the boundary receive different boundary indicators + * (@ref GlossBoundaryIndicator), + * allowing them to be distinguished for the purpose of attaching geometry + * objects and evaluating different boundary conditions. * + * This namespace also provides a function + * GridGenerator::laplace_transformation that smoothly transforms a domain + * into another one. This can be used to + * transform basic geometries to more complicated ones, like a + * shell to a grid of an airfoil, for example. * * @ingroup grid */ -class GridGenerator +namespace GridGenerator { -public: - /** - * Declare type for number of cell. - */ - typedef types::global_dof_index size_type; - /** * Initialize the given triangulation with a hypercube (line in 1D, square * in 2D, etc) consisting of exactly one cell. The hypercube volume is the @@ -79,9 +70,9 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void hyper_cube (Triangulation &tria, - const double left = 0., - const double right= 1.); + void hyper_cube (Triangulation &tria, + const double left = 0., + const double right= 1.); /** * Same as hyper_cube(), but with the difference that not only one cell is @@ -97,10 +88,10 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void subdivided_hyper_cube (Triangulation &tria, - const unsigned int repetitions, - const double left = 0., - const double right= 1.); + void subdivided_hyper_cube (Triangulation &tria, + const unsigned int repetitions, + const double left = 0., + const double right= 1.); /** * Create a coordinate-parallel brick from the two diagonally opposite @@ -118,10 +109,10 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void hyper_rectangle (Triangulation &tria, - const Point &p1, - const Point &p2, - const bool colorize = false); + void hyper_rectangle (Triangulation &tria, + const Point &p1, + const Point &p2, + const bool colorize = false); /** * Create a coordinate-parallel parallelepiped from the two diagonally @@ -155,13 +146,12 @@ public: * program. */ template - static void subdivided_hyper_rectangle (Triangulation &tria, const std::vector &repetitions, const Point &p1, const Point &p2, - const bool colorize=false); + const bool colorize=false); /** * Like the previous function. However, here the second argument does not @@ -179,13 +169,12 @@ public: * specified by the points @p p1 and @p p2. */ template - static void - subdivided_hyper_rectangle(Triangulation &tria, - const std::vector > &step_sizes, - const Point &p_1, - const Point &p_2, - const bool colorize); + subdivided_hyper_rectangle (Triangulation &tria, + const std::vector > &step_sizes, + const Point &p_1, + const Point &p_2, + const bool colorize); /** * Like the previous function, but with the following twist: the @p @@ -196,13 +185,12 @@ public: * i.e. the domain will have a void there. */ template - static void subdivided_hyper_rectangle (Triangulation &tria, const std::vector< std::vector > &spacing, const Point &p, - const Table &material_id, - const bool colorize=false); + const Table &material_id, + const bool colorize=false); /** * A parallelogram. The first corner point is the origin. The dim @@ -215,21 +203,19 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void - parallelogram(Triangulation &tria, - const Point (&corners)[dim], - const bool colorize=false); + parallelogram (Triangulation &tria, + const Point (&corners) [dim], + const bool colorize=false); /** * @deprecated Use the other function of same name. */ template - static void - parallelogram(Triangulation &tria, - const Tensor<2,dim> &corners, - const bool colorize=false) DEAL_II_DEPRECATED; + parallelogram (Triangulation &tria, + const Tensor<2,dim> &corners, + const bool colorize=false) DEAL_II_DEPRECATED; /** * A parallelepiped. The first corner point is the origin. The @@ -249,11 +235,10 @@ public: * function. */ template - static void - parallelepiped (Triangulation &tria, - const Point (&corners) [dim], - const bool colorize = false); + parallelepiped (Triangulation &tria, + const Point (&corners) [dim], + const bool colorize = false); /** * A subdivided parallelepiped. The first corner point is the @@ -268,10 +253,9 @@ public: * function. */ template - static void subdivided_parallelepiped (Triangulation &tria, - const size_type n_subdivisions, + const unsigned int n_subdivisions, const Point (&corners) [dim], const bool colorize = false); @@ -284,10 +268,9 @@ public: * function. */ template - static void subdivided_parallelepiped (Triangulation &tria, - const size_type ( n_subdivisions) [dim], + const unsigned int (n_subdivisions) [dim], const Point (&corners) [dim], const bool colorize = false); @@ -307,11 +290,11 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void enclosed_hyper_cube (Triangulation &tria, - const double left = 0., - const double right= 1., - const double thickness = 1., - const bool colorize = false); + void enclosed_hyper_cube (Triangulation &tria, + const double left = 0., + const double right= 1., + const double thickness = 1., + const bool colorize = false); /** * Initialize the given triangulation with a hyperball, i.e. a circle or a @@ -328,9 +311,9 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void hyper_ball (Triangulation &tria, - const Point ¢er = Point(), - const double radius = 1.); + void hyper_ball (Triangulation &tria, + const Point ¢er = Point(), + const double radius = 1.); /** * This class produces a half hyper-ball around center, which @@ -346,9 +329,9 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void half_hyper_ball (Triangulation &tria, - const Point ¢er = Point(), - const double radius = 1.); + void half_hyper_ball (Triangulation &tria, + const Point ¢er = Point(), + const double radius = 1.); /** * Create a cylinder around the x-axis. The cylinder extends from @@ -366,9 +349,9 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void cylinder (Triangulation &tria, - const double radius = 1., - const double half_length = 1.); + void cylinder (Triangulation &tria, + const double radius = 1., + const double half_length = 1.); /** * Create a cutted cone around the x-axis. The cone extends from @@ -395,11 +378,11 @@ public: * @author Markus Bürg, 2009 */ template - static void + void truncated_cone (Triangulation &tria, - const double radius_0 = 1.0, - const double radius_1 = 0.5, - const double half_length = 1.0); + const double radius_0 = 1.0, + const double radius_1 = 0.5, + const double half_length = 1.0); /** * Initialize the given triangulation with a hyper-L consisting of exactly @@ -417,9 +400,9 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void hyper_L (Triangulation &tria, - const double left = -1., - const double right= 1.); + void hyper_L (Triangulation &tria, + const double left = -1., + const double right= 1.); /** * Initialize the given Triangulation with a hypercube with a slit. In each @@ -437,10 +420,10 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void hyper_cube_slit (Triangulation &tria, - const double left = 0., - const double right= 1., - const bool colorize = false); + void hyper_cube_slit (Triangulation &tria, + const double left = 0., + const double right = 1., + const bool colorize = false); /** * Produce a hyper-shell, the region between two spheres around @@ -491,12 +474,12 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void hyper_shell (Triangulation &tria, - const Point ¢er, - const double inner_radius, - const double outer_radius, - const size_type n_cells = 0, - bool colorize = false); + void hyper_shell (Triangulation &tria, + const Point ¢er, + const double inner_radius, + const double outer_radius, + const unsigned int n_cells = 0, + bool colorize = false); /** * Produce a half hyper-shell, i.e. the space between two circles in two @@ -520,12 +503,12 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void half_hyper_shell (Triangulation &tria, - const Point ¢er, - const double inner_radius, - const double outer_radius, - const size_type n_cells = 0, - const bool colorize = false); + void half_hyper_shell (Triangulation &tria, + const Point ¢er, + const double inner_radius, + const double outer_radius, + const unsigned int n_cells = 0, + const bool colorize = false); /** @@ -549,12 +532,12 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void quarter_hyper_shell (Triangulation &tria, - const Point ¢er, - const double inner_radius, - const double outer_radius, - const size_type n_cells = 0, - const bool colorize = false); + void quarter_hyper_shell (Triangulation &tria, + const Point ¢er, + const double inner_radius, + const double outer_radius, + const unsigned int n_cells = 0, + const bool colorize = false); /** * Produce a domain that is the space between two cylinders in 3d, with @@ -569,12 +552,12 @@ public: * @note The triangulation needs to be void upon calling this function. */ template - static void cylinder_shell (Triangulation &tria, - const double length, - const double inner_radius, - const double outer_radius, - const size_type n_radial_cells = 0, - const size_type n_axial_cells = 0); + void cylinder_shell (Triangulation &tria, + const double length, + const double inner_radius, + const double outer_radius, + const unsigned int n_radial_cells = 0, + const unsigned int n_axial_cells = 0); @@ -592,9 +575,9 @@ public: * torus. */ - static void torus (Triangulation<2,3> &tria, - const double R, - const double r); + void torus (Triangulation<2,3> &tria, + const double R, + const double r); /** @@ -622,12 +605,13 @@ public: * get the number 0 and the hole gets number 1. */ template - static void hyper_cube_with_cylindrical_hole (Triangulation &triangulation, - const double inner_radius = .25, - const double outer_radius = .5, - const double L = .5, - const size_type repetition = 1, - const bool colorize = false); + void hyper_cube_with_cylindrical_hole ( + Triangulation &triangulation, + const double inner_radius = .25, + const double outer_radius = .5, + const double L = .5, + const unsigned int repetition = 1, + const bool colorize = false); /** * Produce a ring of cells in 3D that is cut open, twisted and glued @@ -639,11 +623,11 @@ public: * @param R The radius of the circle, which forms the middle line of the torus containing the loop of cells. Must be greater than @p r. * @param r The radius of the cylinder bend together as loop. */ - static void moebius (Triangulation<3,3> &tria, - const size_type n_cells, - const unsigned int n_rotations, - const double R, - const double r); + void moebius (Triangulation<3,3> &tria, + const unsigned int n_cells, + const unsigned int n_rotations, + const double R, + const double r); /** * Given the two triangulations specified as the first two arguments, create @@ -676,7 +660,6 @@ public: * GridTools::create_union_triangulation . */ template - static void merge_triangulations (const Triangulation &triangulation_1, const Triangulation &triangulation_2, @@ -690,12 +673,11 @@ public: * to the corresponding side walls in z direction. The bottom and top * get the next two free boundary indicators. */ - static void - extrude_triangulation(const Triangulation<2, 2> &input, - const size_type n_slices, - const double height, - Triangulation<3,3> &result); + extrude_triangulation (const Triangulation<2, 2> &input, + const unsigned int n_slices, + const double height, + Triangulation<3,3> &result); /** * This function transformes the @p Triangulation @p tria smoothly to a @@ -712,9 +694,8 @@ public: * @deprecated This function has been moved to GridTools::laplace_transform */ template - static void laplace_transformation (Triangulation &tria, - const std::map > &new_points) DEAL_II_DEPRECATED; + const std::map > &new_points) DEAL_II_DEPRECATED; /** * Exception @@ -734,67 +715,7 @@ public: int, << "The vector of repetitions must have " << arg1 <<" elements."); - -private: - /** - * Perform the action specified by the @p colorize flag of the - * hyper_rectangle() function of this class. - */ - template - static - void - colorize_hyper_rectangle (Triangulation &tria); - - /** - * Perform the action specified by the @p colorize flag of the - * subdivided_hyper_rectangle() function of this class. This function is - * singled out because it is dimension specific. - */ - template - static - void - colorize_subdivided_hyper_rectangle (Triangulation &tria, - const Point &p1, - const Point &p2, - const double epsilon); - - /** - * Assign boundary number zero to the inner shell boundary and 1 to the - * outer. - */ - template - static - void - colorize_hyper_shell (Triangulation &tria, - const Point ¢er, - const double inner_radius, - const double outer_radius); - - - /** - * Assign boundary number zero the inner shell boundary, one to the outer - * shell boundary, two to the face with x=0, three to the face with y=0, - * four to the face with z=0. - */ - template - static - void - colorize_quarter_hyper_shell(Triangulation &tria, - const Point ¢er, - const double inner_radius, - const double outer_radius); - - /** - * Solve the Laplace equation for @p laplace_transformation function for one - * of the @p dim space dimensions. Externalized into a function of its own - * in order to allow parallel execution. - */ - static - void - laplace_solve (const SparseMatrix &S, - const std::map &m, - Vector &u); -}; +} diff --git a/deal.II/include/deal.II/grid/grid_tools.h b/deal.II/include/deal.II/grid/grid_tools.h index 1df740cff6..bdbc8ab792 100644 --- a/deal.II/include/deal.II/grid/grid_tools.h +++ b/deal.II/include/deal.II/grid/grid_tools.h @@ -237,16 +237,32 @@ namespace GridTools Triangulation<2> &triangulation); /** - * This function transformes the @p Triangulation @p tria smoothly to a - * domain that is described by the boundary points in the map @p - * new_points. This map maps the point indices to the boundary points in the - * transformed domain. - * - * Note, that the @p Triangulation is changed in-place, therefore you don't - * need to keep two triangulations, but the given triangulation is changed - * (overwritten). - * - * In 1d, this function is not currently implemented. + * Transform the given triangulation smoothly to a different domain where + * each of the vertices at the boundary of the triangulation is mapped to + * the corresponding points in the @p new_points map. + * + * The way this function works is that it solves a Laplace equation for each + * of the dim components of a displacement field that maps the current + * domain into one described by @p new_points . The @p new_points array + * therefore represents the boundary values of this displacement field. + * The function then evaluates this displacement field at each vertex in + * the interior and uses it to place the mapped vertex where the + * displacement field locates it. Because the solution of the Laplace + * equation is smooth, this guarantees a smooth mapping from the old + * domain to the new one. + * + * @param[in] new_points The locations where a subset of the existing vertices + * are to be placed. Typically, this would be a map from the vertex indices + * of all nodes on the boundary to their new locations, thus completely + * specifying the geometry of the mapped domain. However, it may also include + * interior points if necessary and it does not need to include all boundary + * vertices (although you then lose control over the exact shape of the mapped + * domain). + * + * @param[in,out] tria The Triangulation object. This object is changed in-place, + * i.e., the previous locations of vertices are overwritten. + * + * @note This function is not currently implemented for the 1d case. */ template void laplace_transform (const std::map > &new_points, diff --git a/deal.II/include/deal.II/grid/tria_accessor.h b/deal.II/include/deal.II/grid/tria_accessor.h index 6705f5ded3..984374f98f 100644 --- a/deal.II/include/deal.II/grid/tria_accessor.h +++ b/deal.II/include/deal.II/grid/tria_accessor.h @@ -26,12 +26,8 @@ #include #include +#include -namespace std -{ - template - struct pair; -} DEAL_II_NAMESPACE_OPEN diff --git a/deal.II/include/deal.II/hp/fe_values.h b/deal.II/include/deal.II/hp/fe_values.h index fd02273faa..d077e4d838 100644 --- a/deal.II/include/deal.II/hp/fe_values.h +++ b/deal.II/include/deal.II/hp/fe_values.h @@ -64,63 +64,45 @@ namespace internal { public: /** - * Constructor. Set the fields - * of this class to the values - * indicated by the parameters - * to the constructor. + * Constructor. Set the fields of this class to the values indicated by + * the parameters to the constructor. */ FEValuesBase (const dealii::hp::MappingCollection &mapping_collection, const dealii::hp::FECollection &fe_collection, const dealii::hp::QCollection &q_collection, const UpdateFlags update_flags); /** - * Constructor. Set the fields - * of this class to the values - * indicated by the parameters - * to the constructor, and - * choose a @p MappingQ1 - * object for the mapping - * object. + * Constructor. Set the fields of this class to the values indicated by + * the parameters to the constructor, and choose a @p MappingQ1 object + * for the mapping object. */ FEValuesBase (const dealii::hp::FECollection &fe_collection, const dealii::hp::QCollection &q_collection, const UpdateFlags update_flags); /** - * Get a reference to the - * collection of finite - * element objects used here. + * Get a reference to the collection of finite element objects used + * here. */ const dealii::hp::FECollection & get_fe_collection () const; /** - * Return a reference to the @p - * FEValues object selected by the - * last call to - * select_fe_values(). select_fe_values() - * in turn is called when you called - * the @p reinit function of the - * hp::FE*Values class the - * last time. + * Return a reference to the @p FEValues object selected by the last + * call to select_fe_values(). select_fe_values() in turn is called when + * you called the @p reinit function of the hp::FE*Values class + * the last time. */ const FEValues &get_present_fe_values () const; protected: /** - * Select a FEValues object - * suitable for the given FE, - * quadrature, and mapping - * indices. If such an object - * doesn't yet exist, create - * one. + * Select a FEValues object suitable for the given FE, quadrature, and + * mapping indices. If such an object doesn't yet exist, create one. * - * The function returns a - * writable reference so that - * derived classes can also - * reinit() the selected - * FEValues object. + * The function returns a writable reference so that derived classes can + * also reinit() the selected FEValues object. */ FEValues & select_fe_values (const unsigned int fe_index, @@ -129,68 +111,44 @@ namespace internal protected: /** - * A pointer to the - * collection of finite - * elements to be used. + * A pointer to the collection of finite elements to be used. */ const SmartPointer, FEValuesBase > fe_collection; /** - * A pointer to the - * collection of mappings to - * be used. + * A pointer to the collection of mappings to be used. */ const SmartPointer, FEValuesBase > mapping_collection; /** - * Copy of the quadrature - * collection object - * provided to the - * constructor. + * Copy of the quadrature collection object provided to the constructor. */ const dealii::hp::QCollection q_collection; private: /** - * A table in which we store - * pointers to fe_values - * objects for different - * finite element, mapping, - * and quadrature objects - * from our collection. The - * first index indicates the - * index of the finite - * element within the - * fe_collection, the second - * the index of the mapping - * within the mapping - * collection, and the last - * one the index of the - * quadrature formula within - * the q_collection. + * A table in which we store pointers to fe_values objects for different + * finite element, mapping, and quadrature objects from our + * collection. The first index indicates the index of the finite element + * within the fe_collection, the second the index of the mapping within + * the mapping collection, and the last one the index of the quadrature + * formula within the q_collection. * - * Initially, all entries - * have zero pointers, and we - * will allocate them lazily - * as needed in - * select_fe_values(). + * Initially, all entries have zero pointers, and we will allocate them + * lazily as needed in select_fe_values(). */ Table<3,std_cxx1x::shared_ptr > fe_values_table; /** - * Set of indices pointing at - * the fe_values object - * selected last time the - * select_fe_value() function - * was called. + * Set of indices pointing at the fe_values object selected last time + * the select_fe_value() function was called. */ TableIndices<3> present_fe_values_index; /** - * Values of the update flags as - * given to the constructor. + * Values of the update flags as given to the constructor. */ const UpdateFlags update_flags; }; @@ -259,24 +217,13 @@ namespace hp static const unsigned int space_dimension = spacedim; /** - * Constructor. Initialize this - * object with the given - * parameters. + * Constructor. Initialize this object with the given parameters. * - * The finite element - * collection parameter is - * actually ignored, but is in - * the signature of this - * function to make it - * compatible with the - * signature of the respective - * constructor of the usual - * FEValues object, with - * the respective parameter in - * that function also being the - * return value of the - * DoFHandler::get_fe() - * function. + * The finite element collection parameter is actually ignored, but is in + * the signature of this function to make it compatible with the signature + * of the respective constructor of the usual FEValues object, with the + * respective parameter in that function also being the return value of + * the DoFHandler::get_fe() function. */ FEValues (const dealii::hp::MappingCollection &mapping_collection, const dealii::hp::FECollection &fe_collection, @@ -285,26 +232,14 @@ namespace hp /** - * Constructor. Initialize this - * object with the given - * parameters, and choose a - * @p MappingQ1 object for the - * mapping object. + * Constructor. Initialize this object with the given parameters, and + * choose a @p MappingQ1 object for the mapping object. * - * The finite element - * collection parameter is - * actually ignored, but is in - * the signature of this - * function to make it - * compatible with the - * signature of the respective - * constructor of the usual - * FEValues object, with - * the respective parameter in - * that function also being the - * return value of the - * DoFHandler::get_fe() - * function. + * The finite element collection parameter is actually ignored, but is in + * the signature of this function to make it compatible with the signature + * of the respective constructor of the usual FEValues object, with the + * respective parameter in that function also being the return value of + * the DoFHandler::get_fe() function. */ FEValues (const hp::FECollection &fe_collection, const hp::QCollection &q_collection, @@ -312,103 +247,50 @@ namespace hp /** - * Reinitialize the object for - * the given cell. + * Reinitialize the object for the given cell. * - * After the call, you can get - * an FEValues object using the - * get_present_fe_values() - * function that corresponds to - * the present cell. For this - * FEValues object, we use the - * additional arguments - * described below to determine - * which finite element, - * mapping, and quadrature - * formula to use. They are - * order in such a way that the - * arguments one may want to - * change most frequently come - * first. The rules for these - * arguments are as follows: + * After the call, you can get an FEValues object using the + * get_present_fe_values() function that corresponds to the present + * cell. For this FEValues object, we use the additional arguments + * described below to determine which finite element, mapping, and + * quadrature formula to use. They are order in such a way that the + * arguments one may want to change most frequently come first. The rules + * for these arguments are as follows: * - * If the @p fe_index argument - * to this function is left at - * its default value, then we - * use that finite element - * within the hp::FECollection - * passed to the constructor of - * this class with index given - * by - * cell-@>active_fe_index(). Consequently, - * the hp::FECollection - * argument given to this - * object should really be the - * same as that used in the - * construction of the - * hp::DofHandler associated - * with the present cell. On - * the other hand, if a value - * is given for this argument, - * it overrides the choice of + * If the @p fe_index argument to this function is left at its default + * value, then we use that finite element within the hp::FECollection + * passed to the constructor of this class with index given by + * cell-@>active_fe_index(). Consequently, the + * hp::FECollection argument given to this object should really be the + * same as that used in the construction of the hp::DofHandler associated + * with the present cell. On the other hand, if a value is given for this + * argument, it overrides the choice of * cell-@>active_fe_index(). * - * If the @p q_index argument - * is left at its default - * value, then we use that - * quadrature formula within - * the hp::QCollection passed - * to the constructor of this - * class with index given by - * cell-@>active_fe_index(), - * i.e. the same index as that - * of the finite element. In - * this case, there should be a - * corresponding quadrature - * formula for each finite - * element in the - * hp::FECollection. As a - * special case, if the - * quadrature collection - * contains only a single - * element (a frequent case if - * one wants to use the same - * quadrature object for all - * finite elements in an hp - * discretization, even if that - * may not be the most - * efficient), then this single - * quadrature is used unless a - * different value for this - * argument is specified. On - * the other hand, if a value - * is given for this argument, - * it overrides the choice of - * cell-@>active_fe_index() - * or the choice for the single + * If the @p q_index argument is left at its default value, then we use + * that quadrature formula within the hp::QCollection passed to the + * constructor of this class with index given by + * cell-@>active_fe_index(), i.e. the same index as that of + * the finite element. In this case, there should be a corresponding + * quadrature formula for each finite element in the hp::FECollection. As + * a special case, if the quadrature collection contains only a single + * element (a frequent case if one wants to use the same quadrature object + * for all finite elements in an hp discretization, even if that may not + * be the most efficient), then this single quadrature is used unless a + * different value for this argument is specified. On the other hand, if a + * value is given for this argument, it overrides the choice of + * cell-@>active_fe_index() or the choice for the single * quadrature. * - * If the @p mapping_index - * argument is left at its - * default value, then we use - * that mapping object within - * the hp::MappingCollection - * passed to the constructor of - * this class with index given - * by - * cell-@>active_fe_index(), - * i.e. the same index as that - * of the finite - * element. As above, if the - * mapping collection contains - * only a single element (a - * frequent case if one wants - * to use a MappingQ1 object - * for all finite elements in - * an hp discretization), then - * this single mapping is used - * unless a different value for - * this argument is specified. + * If the @p mapping_index argument is left at its default value, then we + * use that mapping object within the hp::MappingCollection passed to the + * constructor of this class with index given by + * cell-@>active_fe_index(), i.e. the same index as that of + * the finite element. As above, if the mapping collection contains only a + * single element (a frequent case if one wants to use a MappingQ1 object + * for all finite elements in an hp discretization), then this single + * mapping is used unless a different value for this argument is + * specified. */ template void @@ -418,33 +300,17 @@ namespace hp const unsigned int fe_index = numbers::invalid_unsigned_int); /** - * Like the previous function, - * but for non-hp - * iterators. The reason this - * (and the other non-hp - * iterator) function exists is - * so that one can use - * hp::FEValues not only for - * hp::DoFhandler objects, but - * for all sorts of DoFHandler - * objects, and triangulations - * not associated with - * DoFHandlers in general. + * Like the previous function, but for non-hp iterators. The reason this + * (and the other non-hp iterator) function exists is so that one can use + * hp::FEValues not only for hp::DoFhandler objects, but for all sorts of + * DoFHandler objects, and triangulations not associated with DoFHandlers + * in general. * - * Since - * cell-@>active_fe_index() - * doesn't make sense for - * triangulation iterators, - * this function chooses the - * zero-th finite element, - * mapping, and quadrature - * object from the relevant - * constructions passed to the - * constructor of this - * object. The only exception - * is if you specify a value - * different from the default - * value for any of these last + * Since cell-@>active_fe_index() doesn't make sense for + * triangulation iterators, this function chooses the zero-th finite + * element, mapping, and quadrature object from the relevant constructions + * passed to the constructor of this object. The only exception is if you + * specify a value different from the default value for any of these last * three arguments. */ void @@ -486,24 +352,13 @@ namespace hp { public: /** - * Constructor. Initialize this - * object with the given - * parameters. + * Constructor. Initialize this object with the given parameters. * - * The finite element - * collection parameter is - * actually ignored, but is in - * the signature of this - * function to make it - * compatible with the - * signature of the respective - * constructor of the usual - * FEValues object, with - * the respective parameter in - * that function also being the - * return value of the - * DoFHandler::get_fe() - * function. + * The finite element collection parameter is actually ignored, but is in + * the signature of this function to make it compatible with the signature + * of the respective constructor of the usual FEValues object, with the + * respective parameter in that function also being the return value of + * the DoFHandler::get_fe() function. */ FEFaceValues (const hp::MappingCollection &mapping_collection, const hp::FECollection &fe_collection, @@ -512,129 +367,64 @@ namespace hp /** - * Constructor. Initialize this - * object with the given - * parameters, and choose a - * @p MappingQ1 object for the - * mapping object. + * Constructor. Initialize this object with the given parameters, and + * choose a @p MappingQ1 object for the mapping object. * - * The finite element - * collection parameter is - * actually ignored, but is in - * the signature of this - * function to make it - * compatible with the - * signature of the respective - * constructor of the usual - * FEValues object, with - * the respective parameter in - * that function also being the - * return value of the - * DoFHandler::get_fe() - * function. + * The finite element collection parameter is actually ignored, but is in + * the signature of this function to make it compatible with the signature + * of the respective constructor of the usual FEValues object, with the + * respective parameter in that function also being the return value of + * the DoFHandler::get_fe() function. */ FEFaceValues (const hp::FECollection &fe_collection, const hp::QCollection &q_collection, const UpdateFlags update_flags); /** - * Reinitialize the object for - * the given cell and face. + * Reinitialize the object for the given cell and face. * - * After the call, you can get - * an FEFaceValues object using the - * get_present_fe_values() - * function that corresponds to - * the present cell. For this - * FEFaceValues object, we use the - * additional arguments - * described below to determine - * which finite element, - * mapping, and quadrature - * formula to use. They are - * order in such a way that the - * arguments one may want to - * change most frequently come - * first. The rules for these - * arguments are as follows: + * After the call, you can get an FEFaceValues object using the + * get_present_fe_values() function that corresponds to the present + * cell. For this FEFaceValues object, we use the additional arguments + * described below to determine which finite element, mapping, and + * quadrature formula to use. They are order in such a way that the + * arguments one may want to change most frequently come first. The rules + * for these arguments are as follows: * - * If the @p fe_index argument - * to this function is left at - * its default value, then we - * use that finite element - * within the hp::FECollection - * passed to the constructor of - * this class with index given - * by - * cell-@>active_fe_index(). Consequently, - * the hp::FECollection - * argument given to this - * object should really be the - * same as that used in the - * construction of the - * hp::DofHandler associated - * with the present cell. On - * the other hand, if a value - * is given for this argument, - * it overrides the choice of + * If the @p fe_index argument to this function is left at its default + * value, then we use that finite element within the hp::FECollection + * passed to the constructor of this class with index given by + * cell-@>active_fe_index(). Consequently, the + * hp::FECollection argument given to this object should really be the + * same as that used in the construction of the hp::DofHandler associated + * with the present cell. On the other hand, if a value is given for this + * argument, it overrides the choice of * cell-@>active_fe_index(). * - * If the @p q_index argument - * is left at its default - * value, then we use that - * quadrature formula within - * the hp::QCollection passed - * to the constructor of this - * class with index given by - * cell-@>active_fe_index(), - * i.e. the same index as that - * of the finite element. In - * this case, there should be a - * corresponding quadrature - * formula for each finite - * element in the - * hp::FECollection. As a - * special case, if the - * quadrature collection - * contains only a single - * element (a frequent case if - * one wants to use the same - * quadrature object for all - * finite elements in an hp - * discretization, even if that - * may not be the most - * efficient), then this single - * quadrature is used unless a - * different value for this - * argument is specified. On - * the other hand, if a value - * is given for this argument, - * it overrides the choice of - * cell-@>active_fe_index() - * or the choice for the single + * If the @p q_index argument is left at its default value, then we use + * that quadrature formula within the hp::QCollection passed to the + * constructor of this class with index given by + * cell-@>active_fe_index(), i.e. the same index as that of + * the finite element. In this case, there should be a corresponding + * quadrature formula for each finite element in the hp::FECollection. As + * a special case, if the quadrature collection contains only a single + * element (a frequent case if one wants to use the same quadrature object + * for all finite elements in an hp discretization, even if that may not + * be the most efficient), then this single quadrature is used unless a + * different value for this argument is specified. On the other hand, if a + * value is given for this argument, it overrides the choice of + * cell-@>active_fe_index() or the choice for the single * quadrature. * - * If the @p mapping_index - * argument is left at its - * default value, then we use - * that mapping object within - * the hp::MappingCollection - * passed to the constructor of - * this class with index given - * by - * cell-@>active_fe_index(), - * i.e. the same index as that - * of the finite - * element. As above, if the - * mapping collection contains - * only a single element (a - * frequent case if one wants - * to use a MappingQ1 object - * for all finite elements in - * an hp discretization), then - * this single mapping is used - * unless a different value for - * this argument is specified. + * If the @p mapping_index argument is left at its default value, then we + * use that mapping object within the hp::MappingCollection passed to the + * constructor of this class with index given by + * cell-@>active_fe_index(), i.e. the same index as that of + * the finite element. As above, if the mapping collection contains only a + * single element (a frequent case if one wants to use a MappingQ1 object + * for all finite elements in an hp discretization), then this single + * mapping is used unless a different value for this argument is + * specified. */ template void @@ -645,33 +435,17 @@ namespace hp const unsigned int fe_index = numbers::invalid_unsigned_int); /** - * Like the previous function, - * but for non-hp - * iterators. The reason this - * (and the other non-hp - * iterator) function exists is - * so that one can use - * hp::FEValues not only for - * hp::DoFhandler objects, but - * for all sorts of DoFHandler - * objects, and triangulations - * not associated with - * DoFHandlers in general. + * Like the previous function, but for non-hp iterators. The reason this + * (and the other non-hp iterator) function exists is so that one can use + * hp::FEValues not only for hp::DoFhandler objects, but for all sorts of + * DoFHandler objects, and triangulations not associated with DoFHandlers + * in general. * - * Since - * cell-@>active_fe_index() - * doesn't make sense for - * triangulation iterators, - * this function chooses the - * zero-th finite element, - * mapping, and quadrature - * object from the relevant - * constructions passed to the - * constructor of this - * object. The only exception - * is if you specify a value - * different from the default - * value for any of these last + * Since cell-@>active_fe_index() doesn't make sense for + * triangulation iterators, this function chooses the zero-th finite + * element, mapping, and quadrature object from the relevant constructions + * passed to the constructor of this object. The only exception is if you + * specify a value different from the default value for any of these last * three arguments. */ void @@ -696,24 +470,13 @@ namespace hp { public: /** - * Constructor. Initialize this - * object with the given - * parameters. + * Constructor. Initialize this object with the given parameters. * - * The finite element - * collection parameter is - * actually ignored, but is in - * the signature of this - * function to make it - * compatible with the - * signature of the respective - * constructor of the usual - * FEValues object, with - * the respective parameter in - * that function also being the - * return value of the - * DoFHandler::get_fe() - * function. + * The finite element collection parameter is actually ignored, but is in + * the signature of this function to make it compatible with the signature + * of the respective constructor of the usual FEValues object, with the + * respective parameter in that function also being the return value of + * the DoFHandler::get_fe() function. */ FESubfaceValues (const hp::MappingCollection &mapping_collection, const hp::FECollection &fe_collection, @@ -722,108 +485,54 @@ namespace hp /** - * Constructor. Initialize this - * object with the given - * parameters, and choose a - * @p MappingQ1 object for the - * mapping object. + * Constructor. Initialize this object with the given parameters, and + * choose a @p MappingQ1 object for the mapping object. * - * The finite element - * collection parameter is - * actually ignored, but is in - * the signature of this - * function to make it - * compatible with the - * signature of the respective - * constructor of the usual - * FEValues object, with - * the respective parameter in - * that function also being the - * return value of the - * DoFHandler::get_fe() - * function. + * The finite element collection parameter is actually ignored, but is in + * the signature of this function to make it compatible with the signature + * of the respective constructor of the usual FEValues object, with the + * respective parameter in that function also being the return value of + * the DoFHandler::get_fe() function. */ FESubfaceValues (const hp::FECollection &fe_collection, const hp::QCollection &q_collection, const UpdateFlags update_flags); /** - * Reinitialize the object for - * the given cell, face, and subface. + * Reinitialize the object for the given cell, face, and subface. * - * After the call, you can get - * an FESubfaceValues object using the - * get_present_fe_values() - * function that corresponds to - * the present cell. For this - * FESubfaceValues object, we use the - * additional arguments - * described below to determine - * which finite element, - * mapping, and quadrature - * formula to use. They are - * order in such a way that the - * arguments one may want to - * change most frequently come - * first. The rules for these - * arguments are as follows: + * After the call, you can get an FESubfaceValues object using the + * get_present_fe_values() function that corresponds to the present + * cell. For this FESubfaceValues object, we use the additional arguments + * described below to determine which finite element, mapping, and + * quadrature formula to use. They are order in such a way that the + * arguments one may want to change most frequently come first. The rules + * for these arguments are as follows: * - * If the @p q_index argument - * is left at its default - * value, then we use that - * quadrature formula within - * the hp::QCollection passed - * to the constructor of this - * class with index given by - * cell-@>active_fe_index(), - * i.e. the same index as that - * of the finite element. In - * this case, there should be a - * corresponding quadrature - * formula for each finite - * element in the - * hp::FECollection. As a - * special case, if the - * quadrature collection - * contains only a single - * element (a frequent case if - * one wants to use the same - * quadrature object for all - * finite elements in an hp - * discretization, even if that - * may not be the most - * efficient), then this single - * quadrature is used unless a - * different value for this - * argument is specified. On - * the other hand, if a value - * is given for this argument, - * it overrides the choice of - * cell-@>active_fe_index() - * or the choice for the single + * If the @p q_index argument is left at its default value, then we use + * that quadrature formula within the hp::QCollection passed to the + * constructor of this class with index given by + * cell-@>active_fe_index(), i.e. the same index as that of + * the finite element. In this case, there should be a corresponding + * quadrature formula for each finite element in the hp::FECollection. As + * a special case, if the quadrature collection contains only a single + * element (a frequent case if one wants to use the same quadrature object + * for all finite elements in an hp discretization, even if that may not + * be the most efficient), then this single quadrature is used unless a + * different value for this argument is specified. On the other hand, if a + * value is given for this argument, it overrides the choice of + * cell-@>active_fe_index() or the choice for the single * quadrature. * - * If the @p mapping_index - * argument is left at its - * default value, then we use - * that mapping object within - * the hp::MappingCollection - * passed to the constructor of - * this class with index given - * by - * cell-@>active_fe_index(), - * i.e. the same index as that - * of the finite - * element. As above, if the - * mapping collection contains - * only a single element (a - * frequent case if one wants - * to use a MappingQ1 object - * for all finite elements in - * an hp discretization), then - * this single mapping is used - * unless a different value for - * this argument is specified. + * If the @p mapping_index argument is left at its default value, then we + * use that mapping object within the hp::MappingCollection passed to the + * constructor of this class with index given by + * cell-@>active_fe_index(), i.e. the same index as that of + * the finite element. As above, if the mapping collection contains only a + * single element (a frequent case if one wants to use a MappingQ1 object + * for all finite elements in an hp discretization), then this single + * mapping is used unless a different value for this argument is + * specified. */ template void @@ -835,33 +544,17 @@ namespace hp const unsigned int fe_index = numbers::invalid_unsigned_int); /** - * Like the previous function, - * but for non-hp - * iterators. The reason this - * (and the other non-hp - * iterator) function exists is - * so that one can use - * hp::FEValues not only for - * hp::DoFhandler objects, but - * for all sorts of DoFHandler - * objects, and triangulations - * not associated with - * DoFHandlers in general. + * Like the previous function, but for non-hp iterators. The reason this + * (and the other non-hp iterator) function exists is so that one can use + * hp::FEValues not only for hp::DoFhandler objects, but for all sorts of + * DoFHandler objects, and triangulations not associated with DoFHandlers + * in general. * - * Since - * cell-@>active_fe_index() - * doesn't make sense for - * triangulation iterators, - * this function chooses the - * zero-th finite element, - * mapping, and quadrature - * object from the relevant - * constructions passed to the - * constructor of this - * object. The only exception - * is if you specify a value - * different from the default - * value for any of these last + * Since cell-@>active_fe_index() doesn't make sense for + * triangulation iterators, this function chooses the zero-th finite + * element, mapping, and quadrature object from the relevant constructions + * passed to the constructor of this object. The only exception is if you + * specify a value different from the default value for any of these last * three arguments. */ void diff --git a/deal.II/include/deal.II/lac/block_matrix_base.h b/deal.II/include/deal.II/lac/block_matrix_base.h index 56d0067a63..df541b1ae8 100644 --- a/deal.II/include/deal.II/lac/block_matrix_base.h +++ b/deal.II/include/deal.II/lac/block_matrix_base.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -412,6 +413,11 @@ public: */ BlockMatrixBase (); + /** + * Destructor. + */ + ~BlockMatrixBase (); + /** * Copy the given matrix to this * one. The operation throws an @@ -936,7 +942,7 @@ public: /** * Return a reference to the underlying - * BlockIndices data of the rows. + * BlockIndices data of the columns. */ const BlockIndices &get_column_indices () const; @@ -1241,30 +1247,74 @@ protected: private: - /** - * Temporary vector for counting the - * elements written into the - * individual blocks when doing a - * collective add or set. - */ - std::vector counter_within_block; /** - * Temporary vector for column - * indices on each block when writing - * local to global data on each - * sparse matrix. + * A structure containing some fields used by the + * set() and add() functions that is used to pre-sort + * the input fields. Since one can reasonably expect + * to call set() and add() from multiple threads at once + * as long as the matrix indices that are touched are + * disjoint, these temporary data fields need to be + * guarded by a mutex; the structure therefore contains such + * a mutex as a member variable. */ - std::vector > column_indices; + struct TemporaryData + { + /** + * Temporary vector for counting the + * elements written into the + * individual blocks when doing a + * collective add or set. + */ + std::vector counter_within_block; + + /** + * Temporary vector for column + * indices on each block when writing + * local to global data on each + * sparse matrix. + */ + std::vector > column_indices; + + /** + * Temporary vector for storing the + * local values (they need to be + * reordered when writing local to + * global). + */ + std::vector > column_values; + + /** + * A mutex variable used to guard access to the member + * variables of this structure; + */ + Threads::Mutex mutex; + + /** + * Copy operator. This is needed because the default copy + * operator of this class is deleted (since Threads::Mutex is + * not copyable) and hence the default copy operator of the + * enclosing class is also deleted. + * + * The implementation here simply does nothing -- TemporaryData + * objects are just scratch objects that are resized at the + * beginning of their use, so there is no point actually copying + * anything. + */ + TemporaryData & operator = (const TemporaryData &) + { + return *this; + } + }; /** - * Temporary vector for storing the - * local values (they need to be - * reordered when writing local to - * global). + * A set of scratch arrays that can be used by the add() + * and set() functions that take pointers to data to + * pre-sort indices before use. Access from multiple threads + * is synchronized via the mutex variable that is part of the + * structure. */ - std::vector > column_values; - + TemporaryData temporary_data; /** * Make the iterator class a @@ -1736,6 +1786,12 @@ inline BlockMatrixBase::BlockMatrixBase () {} +template +inline +BlockMatrixBase::~BlockMatrixBase () +{ + clear (); +} template @@ -1761,9 +1817,10 @@ BlockMatrixBase::memory_consumption () const MemoryConsumption::memory_consumption(row_block_indices)+ MemoryConsumption::memory_consumption(column_block_indices)+ MemoryConsumption::memory_consumption(sub_objects)+ - MemoryConsumption::memory_consumption(counter_within_block)+ - MemoryConsumption::memory_consumption(column_indices)+ - MemoryConsumption::memory_consumption(column_values); + MemoryConsumption::memory_consumption(temporary_data.counter_within_block)+ + MemoryConsumption::memory_consumption(temporary_data.column_indices)+ + MemoryConsumption::memory_consumption(temporary_data.column_values)+ + sizeof(temporary_data.mutex); for (unsigned int r=0; r::set (const size_type row, { prepare_set_operation(); + // lock access to the temporary data structure to + // allow multiple threads to call this function concurrently + Threads::Mutex::ScopedLock lock (temporary_data.mutex); + // Resize scratch arrays - if (column_indices.size() < this->n_block_cols()) + if (temporary_data.column_indices.size() < this->n_block_cols()) { - column_indices.resize (this->n_block_cols()); - column_values.resize (this->n_block_cols()); - counter_within_block.resize (this->n_block_cols()); + temporary_data.column_indices.resize (this->n_block_cols()); + temporary_data.column_values.resize (this->n_block_cols()); + temporary_data.counter_within_block.resize (this->n_block_cols()); } // Resize sub-arrays to n_cols. This @@ -1983,19 +2044,19 @@ BlockMatrixBase::set (const size_type row, // whether the size of one is large // enough before actually going // through all of them. - if (column_indices[0].size() < n_cols) + if (temporary_data.column_indices[0].size() < n_cols) { for (unsigned int i=0; in_block_cols(); ++i) { - column_indices[i].resize(n_cols); - column_values[i].resize(n_cols); + temporary_data.column_indices[i].resize(n_cols); + temporary_data.column_values[i].resize(n_cols); } } // Reset the number of added elements // in each block to zero. for (unsigned int i=0; in_block_cols(); ++i) - counter_within_block[i] = 0; + temporary_data.counter_within_block[i] = 0; // Go through the column indices to // find out which portions of the @@ -2016,10 +2077,10 @@ BlockMatrixBase::set (const size_type row, const std::pair col_index = this->column_block_indices.global_to_local(col_indices[j]); - const size_type local_index = counter_within_block[col_index.first]++; + const size_type local_index = temporary_data.counter_within_block[col_index.first]++; - column_indices[col_index.first][local_index] = col_index.second; - column_values[col_index.first][local_index] = value; + temporary_data.column_indices[col_index.first][local_index] = col_index.second; + temporary_data.column_values[col_index.first][local_index] = value; } #ifdef DEBUG @@ -2027,7 +2088,7 @@ BlockMatrixBase::set (const size_type row, // the right length has been obtained. size_type length = 0; for (unsigned int i=0; in_block_cols(); ++i) - length += counter_within_block[i]; + length += temporary_data.counter_within_block[i]; Assert (length <= n_cols, ExcInternalError()); #endif @@ -2040,14 +2101,14 @@ BlockMatrixBase::set (const size_type row, row_index = this->row_block_indices.global_to_local (row); for (unsigned int block_col=0; block_col::add (const size_type row, return; } - // Resize scratch arrays - if (column_indices.size() < this->n_block_cols()) + // Lock scratch arrays, then resize them + Threads::Mutex::ScopedLock lock (temporary_data.mutex); + + if (temporary_data.column_indices.size() < this->n_block_cols()) { - column_indices.resize (this->n_block_cols()); - column_values.resize (this->n_block_cols()); - counter_within_block.resize (this->n_block_cols()); + temporary_data.column_indices.resize (this->n_block_cols()); + temporary_data.column_values.resize (this->n_block_cols()); + temporary_data.counter_within_block.resize (this->n_block_cols()); } // Resize sub-arrays to n_cols. This @@ -2228,19 +2291,19 @@ BlockMatrixBase::add (const size_type row, // whether the size of one is large // enough before actually going // through all of them. - if (column_indices[0].size() < n_cols) + if (temporary_data.column_indices[0].size() < n_cols) { for (unsigned int i=0; in_block_cols(); ++i) { - column_indices[i].resize(n_cols); - column_values[i].resize(n_cols); + temporary_data.column_indices[i].resize(n_cols); + temporary_data.column_values[i].resize(n_cols); } } // Reset the number of added elements // in each block to zero. for (unsigned int i=0; in_block_cols(); ++i) - counter_within_block[i] = 0; + temporary_data.counter_within_block[i] = 0; // Go through the column indices to // find out which portions of the @@ -2261,10 +2324,10 @@ BlockMatrixBase::add (const size_type row, const std::pair col_index = this->column_block_indices.global_to_local(col_indices[j]); - const size_type local_index = counter_within_block[col_index.first]++; + const size_type local_index = temporary_data.counter_within_block[col_index.first]++; - column_indices[col_index.first][local_index] = col_index.second; - column_values[col_index.first][local_index] = value; + temporary_data.column_indices[col_index.first][local_index] = col_index.second; + temporary_data.column_values[col_index.first][local_index] = value; } #ifdef DEBUG @@ -2272,7 +2335,7 @@ BlockMatrixBase::add (const size_type row, // the right length has been obtained. size_type length = 0; for (unsigned int i=0; in_block_cols(); ++i) - length += counter_within_block[i]; + length += temporary_data.counter_within_block[i]; Assert (length <= n_cols, ExcInternalError()); #endif @@ -2285,14 +2348,14 @@ BlockMatrixBase::add (const size_type row, row_index = this->row_block_indices.global_to_local (row); for (unsigned int block_col=0; block_colindex1=index2 or constrains index2 so that + * index2=index1. + */ + bool are_identity_constrained (const size_type index1, + const size_type index2) const; + /** * Return the maximum number of other * dofs that one dof is constrained diff --git a/deal.II/include/deal.II/lac/petsc_parallel_block_vector.h b/deal.II/include/deal.II/lac/petsc_parallel_block_vector.h index 7d52ee3792..f55e61d5cc 100644 --- a/deal.II/include/deal.II/lac/petsc_parallel_block_vector.h +++ b/deal.II/include/deal.II/lac/petsc_parallel_block_vector.h @@ -313,6 +313,11 @@ namespace PETScWrappers */ void reinit (const unsigned int num_blocks); + /** + * Returns if this vector is a ghosted vector (and thus read-only). + */ + bool has_ghost_elements() const; + /** * Return a reference to the MPI * communicator object in use with @@ -436,17 +441,25 @@ namespace PETScWrappers return *this; } - - inline BlockVector & BlockVector::operator = (const BlockVector &v) { - BaseClass::operator = (v); - return *this; - } + // we only allow assignment to vectors with the same number of blocks + // or to an empty BlockVector + Assert (n_blocks() == 0 || n_blocks() == v.n_blocks(), + ExcDimensionMismatch(n_blocks(), v.n_blocks())); + + if (this->n_blocks() != v.n_blocks()) + reinit(v.n_blocks()); + for (size_type i=0; in_blocks(); ++i) + this->components[i] = v.block(i); + collect_sizes(); + + return *this; + } inline BlockVector::~BlockVector () @@ -543,6 +556,17 @@ namespace PETScWrappers return block(0).get_mpi_communicator(); } + inline + bool + BlockVector::has_ghost_elements() const + { + bool ghosted=block(0).has_ghost_elements(); +#ifdef DEBUG + for (unsigned int i=0; in_blocks(); ++i) + Assert(block(i).has_ghost_elements()==ghosted, ExcInternalError()); +#endif + return ghosted; + } inline diff --git a/deal.II/include/deal.II/lac/petsc_parallel_sparse_matrix.h b/deal.II/include/deal.II/lac/petsc_parallel_sparse_matrix.h index 6bfa4df7dd..115bb94bfc 100644 --- a/deal.II/include/deal.II/lac/petsc_parallel_sparse_matrix.h +++ b/deal.II/include/deal.II/lac/petsc_parallel_sparse_matrix.h @@ -158,6 +158,11 @@ namespace PETScWrappers */ SparseMatrix (); + /** + * Destructor to free the PETSc object. + */ + ~SparseMatrix (); + /** * Create a sparse matrix of * dimensions @p m times @p n, with diff --git a/deal.II/include/deal.II/lac/petsc_parallel_vector.h b/deal.II/include/deal.II/lac/petsc_parallel_vector.h index 95cdddc214..bc3ee07627 100644 --- a/deal.II/include/deal.II/lac/petsc_parallel_vector.h +++ b/deal.II/include/deal.II/lac/petsc_parallel_vector.h @@ -588,10 +588,38 @@ namespace PETScWrappers Vector & Vector::operator = (const Vector &v) { + if (v.size()==0) + { + // this happens if v has not been initialized to something useful: + // Vector x,v;x=v; + // we skip the code below and create a simple serial vector of + // length 0 + + int ierr; +#if DEAL_II_PETSC_VERSION_LT(3,2,0) + ierr = VecDestroy (vector); +#else + ierr = VecDestroy (&vector); +#endif + AssertThrow (ierr == 0, ExcPETScError(ierr)); + + const int n = 0; + ierr = VecCreateSeq (PETSC_COMM_SELF, n, &vector); + AssertThrow (ierr == 0, ExcPETScError(ierr)); + ghosted = false; + ghost_indices.clear(); + return *this; + } + // if the vectors have different sizes, // then first resize the present one if (size() != v.size()) - reinit (v.communicator, v.size(), v.local_size(), true); + { + if (v.has_ghost_elements()) + reinit( v.locally_owned_elements(), v.ghost_indices, v.communicator); + else + reinit (v.communicator, v.size(), v.local_size(), true); + } const int ierr = VecCopy (v.vector, vector); AssertThrow (ierr == 0, ExcPETScError(ierr)); diff --git a/deal.II/include/deal.II/lac/slepc_solver.h b/deal.II/include/deal.II/lac/slepc_solver.h index b5135d7403..509297a574 100644 --- a/deal.II/include/deal.II/lac/slepc_solver.h +++ b/deal.II/include/deal.II/lac/slepc_solver.h @@ -297,7 +297,7 @@ namespace SLEPcWrappers EPS *get_eps (); /** - * Solve the linear system for n_eigenpairs + * Solve the linear system for n_eigenpairs * eigenstates. Parameter n_converged contains the * actual number of eigenstates that have . converged; this can * be both fewer or more than n_eigenpairs, depending on the diff --git a/deal.II/include/deal.II/lac/sparsity_pattern.h b/deal.II/include/deal.II/lac/sparsity_pattern.h index b327e5b9ab..ada6bbf528 100644 --- a/deal.II/include/deal.II/lac/sparsity_pattern.h +++ b/deal.II/include/deal.II/lac/sparsity_pattern.h @@ -1147,7 +1147,7 @@ public: /** * Write the data of this object en bloc to a file. This is done in a binary * mode, so the output is neither readable by humans nor (probably) by other - * computers using a different operating system of number format. + * computers using a different operating system or number format. * * The purpose of this function is that you can swap out matrices and * sparsity pattern if you are short of memory, want to communicate between diff --git a/deal.II/include/deal.II/lac/sparsity_tools.h b/deal.II/include/deal.II/lac/sparsity_tools.h index 46b7d07308..860eedfae7 100644 --- a/deal.II/include/deal.II/lac/sparsity_tools.h +++ b/deal.II/include/deal.II/lac/sparsity_tools.h @@ -236,7 +236,9 @@ namespace SparsityTools * range of elements stored locally * and should be the one used in * the constructor of the - * CompressedSimpleSparsityPattern. Only + * CompressedSimpleSparsityPattern. + * This should be the locally relevant set. + * Only * rows contained in myrange are * checked in csp for transfer. * This function needs to be used @@ -250,6 +252,19 @@ namespace SparsityTools const std::vector &rows_per_cpu, const MPI_Comm &mpi_comm, const IndexSet &myrange); + + /** + * similar to the function above, but includes support for + * BlockCompressedSimpleSparsityPattern. + * @p owned_set_per_cpu is typically DoFHandler::locally_owned_dofs_per_processor + * and @p myrange are locally_relevant_dofs. + */ + template + void distribute_sparsity_pattern(CSP_t &csp, + const std::vector &owned_set_per_cpu, + const MPI_Comm &mpi_comm, + const IndexSet &myrange); + #endif diff --git a/deal.II/include/deal.II/lac/trilinos_parallel_block_vector.h b/deal.II/include/deal.II/lac/trilinos_parallel_block_vector.h index f35166b1c3..d684216bdc 100644 --- a/deal.II/include/deal.II/lac/trilinos_parallel_block_vector.h +++ b/deal.II/include/deal.II/lac/trilinos_parallel_block_vector.h @@ -127,6 +127,16 @@ namespace TrilinosWrappers explicit BlockVector (const std::vector ¶llel_partitioning, const MPI_Comm &communicator = MPI_COMM_WORLD); + /** + * Creates a BlockVector with ghost elements. @p ghost_values + * may contain any elements in @p parallel_partitioning, they will + * be ignored. + */ + BlockVector (const std::vector ¶llel_partitioning, + const std::vector &ghost_values, + const MPI_Comm &communicator); + + /** * Copy-Constructor. Set all the * properties of the parallel vector @@ -353,6 +363,11 @@ namespace TrilinosWrappers */ bool is_compressed () const; + /** + * Returns if this Vector contains ghost elements. + */ + bool has_ghost_elements() const; + /** * Swap the contents of this * vector and the other vector @@ -431,6 +446,14 @@ namespace TrilinosWrappers } + inline + BlockVector::BlockVector (const std::vector ¶llel_partitioning, + const std::vector &ghost_values, + const MPI_Comm &communicator) + { + reinit(parallel_partitioning, ghost_values, communicator); + } + inline BlockVector::BlockVector (const size_type num_blocks) @@ -510,6 +533,18 @@ namespace TrilinosWrappers } + inline + bool + BlockVector::has_ghost_elements() const + { + bool ghosted=block(0).has_ghost_elements(); +#ifdef DEBUG + for (unsigned int i=0; in_blocks(); ++i) + Assert(block(i).has_ghost_elements()==ghosted, ExcInternalError()); +#endif + return ghosted; + } + inline void BlockVector::swap (BlockVector &v) diff --git a/deal.II/include/deal.II/lac/trilinos_precondition.h b/deal.II/include/deal.II/lac/trilinos_precondition.h index 34a6017f4f..3936118d50 100644 --- a/deal.II/include/deal.II/lac/trilinos_precondition.h +++ b/deal.II/include/deal.II/lac/trilinos_precondition.h @@ -121,13 +121,13 @@ namespace TrilinosWrappers /** * Apply the preconditioner. */ - void vmult (VectorBase &dst, - const VectorBase &src) const; + virtual void vmult (VectorBase &dst, + const VectorBase &src) const; /** * Apply the transpose preconditioner. */ - void Tvmult (VectorBase &dst, + virtual void Tvmult (VectorBase &dst, const VectorBase &src) const; /** @@ -137,8 +137,8 @@ namespace TrilinosWrappers * in the Trilinos wrapper * class. */ - void vmult (dealii::Vector &dst, - const dealii::Vector &src) const; + virtual void vmult (dealii::Vector &dst, + const dealii::Vector &src) const; /** * Apply the transpose preconditioner on @@ -147,8 +147,8 @@ namespace TrilinosWrappers * in the Trilinos wrapper * class. */ - void Tvmult (dealii::Vector &dst, - const dealii::Vector &src) const; + virtual void Tvmult (dealii::Vector &dst, + const dealii::Vector &src) const; /** * Apply the preconditioner on deal.II @@ -156,8 +156,8 @@ namespace TrilinosWrappers * the ones provided in the Trilinos * wrapper class. */ - void vmult (dealii::parallel::distributed::Vector &dst, - const dealii::parallel::distributed::Vector &src) const; + virtual void vmult (dealii::parallel::distributed::Vector &dst, + const dealii::parallel::distributed::Vector &src) const; /** * Apply the transpose preconditioner on deal.II @@ -165,8 +165,8 @@ namespace TrilinosWrappers * the ones provided in the Trilinos * wrapper class. */ - void Tvmult (dealii::parallel::distributed::Vector &dst, - const dealii::parallel::distributed::Vector &src) const; + virtual void Tvmult (dealii::parallel::distributed::Vector &dst, + const dealii::parallel::distributed::Vector &src) const; /** * Exception. @@ -1508,6 +1508,64 @@ namespace TrilinosWrappers + /** + * A wrapper class for an identity preconditioner for Trilinos matrices. + * + * @ingroup TrilinosWrappers + * @ingroup Preconditioners + * @author Bruno Turcksin, 2013 + */ + class PreconditionIdentity : public PreconditionBase + { + public: + + /** + * Apply the preconditioner, i.e., dst = src. + */ + void vmult (VectorBase &dst, + const VectorBase &src) const; + + /** + * Apply the transport conditioner, i.e., dst = src. + */ + void Tvmult (VectorBase &dst, + const VectorBase &src) const; + + /** + * Apply the preconditioner on deal.II data structures + * instead of the ones provided in the Trilinos wrapper class, + * i.e., dst = src. + */ + void vmult (dealii::Vector &dst, + const dealii::Vector &src) const; + + /** + * Apply the transpose preconditioner on deal.II data structures + * instead of the ones provided in the Trilinos wrapper class, + * i.e. dst = src. + */ + void Tvmult (dealii::Vector &dst, + const dealii::Vector &src) const; + + /** + * Apply the preconditioner on deal.II parallel data structures + * instead of the ones provided in the Trilinos wrapper class, + * i.e., dst = src. + */ + void vmult (parallel::distributed::Vector &dst, + const dealii::parallel::distributed::Vector &src) const; + + /** + * Apply the transpose preconditioner on deal.II parallel data structures + * instead of the ones provided in the Trilinos wrapper class, + * i.e., dst = src. + */ + void Tvmult (parallel::distributed::Vector &dst, + const dealii::parallel::distributed::Vector &src) const; + }; + + + // -------------------------- inline and template functions ---------------------- diff --git a/deal.II/include/deal.II/matrix_free/dof_info.templates.h b/deal.II/include/deal.II/matrix_free/dof_info.templates.h index 16c53c268d..8ab56dcc92 100644 --- a/deal.II/include/deal.II/matrix_free/dof_info.templates.h +++ b/deal.II/include/deal.II/matrix_free/dof_info.templates.h @@ -1020,12 +1020,12 @@ no_constraint: k++) { unsigned int cell = partition_list[k]; - unsigned int no_neighbors = connectivity.row_length(cell); + unsigned int n_neighbors = connectivity.row_length(cell); // In the worst case, each neighbor has a different color. So we - // find at least one available color between 0 and no_neighbors. - color_finder.resize(no_neighbors+1); - for (unsigned int j=0; j<=no_neighbors; ++j) + // find at least one available color between 0 and n_neighbors. + color_finder.resize(n_neighbors+1); + for (unsigned int j=0; j<=n_neighbors; ++j) color_finder[j]=true; CompressedSimpleSparsityPattern::row_iterator neighbor = connectivity.row_begin(cell), @@ -1035,7 +1035,7 @@ no_constraint: // Mark the color that a neighbor within the partition has // as taken if (cell_partition[*neighbor] == part && - cell_color[*neighbor] <= no_neighbors) + cell_color[*neighbor] <= n_neighbors) color_finder[cell_color[*neighbor]] = false; } // Choose the smallest color that is not taken for the block diff --git a/deal.II/include/deal.II/multigrid/mg_transfer_component.h b/deal.II/include/deal.II/multigrid/mg_transfer_component.h index 40259aa4dd..305c828532 100644 --- a/deal.II/include/deal.II/multigrid/mg_transfer_component.h +++ b/deal.II/include/deal.II/multigrid/mg_transfer_component.h @@ -19,21 +19,18 @@ #include +#include #include #include #include #include #include -#include -#include #include - - - #include +#include +#include -#include DEAL_II_NAMESPACE_OPEN diff --git a/deal.II/include/deal.II/multigrid/multigrid.h b/deal.II/include/deal.II/multigrid/multigrid.h index 461a93fb56..0ef5bfdf4d 100644 --- a/deal.II/include/deal.II/multigrid/multigrid.h +++ b/deal.II/include/deal.II/multigrid/multigrid.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/deal.II/include/deal.II/numerics/data_out.h b/deal.II/include/deal.II/numerics/data_out.h index bb2d8f01f1..26cf9b1a53 100644 --- a/deal.II/include/deal.II/numerics/data_out.h +++ b/deal.II/include/deal.II/numerics/data_out.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -42,24 +43,15 @@ namespace internal namespace DataOut { /** - * For each vector that has been added - * through the add_data_vector() - * functions, we need to keep track of a - * pointer to it, and allow data - * extraction from it when we generate - * patches. Unfortunately, we need to do - * this for a number of different vector - * types. Fortunately, they all have the - * same interface. So the way we go is to - * have a base class that provides the - * functions to access the vector's - * information, and to have a derived - * template class that can be - * instantiated for each vector - * type. Since the vectors all have the - * same interface, this is no big - * problem, as they can all use the same - * general templatized code. + * For each vector that has been added through the add_data_vector() + * functions, we need to keep track of a pointer to it, and allow data + * extraction from it when we generate patches. Unfortunately, we need to + * do this for a number of different vector types. Fortunately, they all + * have the same interface. So the way we go is to have a base class that + * provides the functions to access the vector's information, and to have + * a derived template class that can be instantiated for each vector + * type. Since the vectors all have the same interface, this is no big + * problem, as they can all use the same general templatized code. * * @author Wolfgang Bangerth, 2004 */ @@ -68,25 +60,21 @@ namespace internal { public: /** - * Constructor. Give a list of names - * for the individual components of - * the vector and their - * interpretation as scalar or vector - * data. This constructor assumes - * that no postprocessor is going to - * be used. + * Constructor. Give a list of names for the individual components of + * the vector and their interpretation as scalar or vector data. This + * constructor assumes that no postprocessor is going to be used. */ - DataEntryBase (const std::vector &names, + DataEntryBase (const DH *dofs, + const std::vector &names, const std::vector &data_component_interpretation); /** - * Constructor when a data - * postprocessor is going to be - * used. In that case, the names and - * vector declarations are going to - * be acquired from the postprocessor. + * Constructor when a data postprocessor is going to be used. In that + * case, the names and vector declarations are going to be acquired from + * the postprocessor. */ - DataEntryBase (const DataPostprocessor *data_postprocessor); + DataEntryBase (const DH *dofs, + const DataPostprocessor *data_postprocessor); /** * Destructor made virtual. @@ -94,8 +82,7 @@ namespace internal virtual ~DataEntryBase (); /** - * Assuming that the stored vector is - * a cell vector, extract the given + * Assuming that the stored vector is a cell vector, extract the given * element from it. */ virtual @@ -103,10 +90,8 @@ namespace internal get_cell_data_value (const unsigned int cell_number) const = 0; /** - * Given a FEValuesBase object, - * extract the values on the present - * cell from the vector we actually - * store. + * Given a FEValuesBase object, extract the values on the present cell + * from the vector we actually store. */ virtual void @@ -114,12 +99,9 @@ namespace internal std::vector &patch_values) const = 0; /** - * Given a FEValuesBase object, - * extract the values on the present - * cell from the vector we actually - * store. This function does the same - * as the one above but for - * vector-valued finite elements. + * Given a FEValuesBase object, extract the values on the present cell + * from the vector we actually store. This function does the same as the + * one above but for vector-valued finite elements. */ virtual void @@ -127,10 +109,8 @@ namespace internal std::vector > &patch_values_system) const = 0; /** - * Given a FEValuesBase object, - * extract the gradients on the present - * cell from the vector we actually - * store. + * Given a FEValuesBase object, extract the gradients on the present + * cell from the vector we actually store. */ virtual void @@ -138,12 +118,9 @@ namespace internal std::vector > &patch_gradients) const = 0; /** - * Given a FEValuesBase object, - * extract the gradients on the present - * cell from the vector we actually - * store. This function does the same - * as the one above but for - * vector-valued finite elements. + * Given a FEValuesBase object, extract the gradients on the present + * cell from the vector we actually store. This function does the same + * as the one above but for vector-valued finite elements. */ virtual void @@ -151,10 +128,8 @@ namespace internal std::vector > > &patch_gradients_system) const = 0; /** - * Given a FEValuesBase object, extract - * the second derivatives on the - * present cell from the vector we - * actually store. + * Given a FEValuesBase object, extract the second derivatives on the + * present cell from the vector we actually store. */ virtual void @@ -162,12 +137,9 @@ namespace internal std::vector > &patch_hessians) const = 0; /** - * Given a FEValuesBase object, extract - * the second derivatives on the - * present cell from the vector we - * actually store. This function does - * the same as the one above but for - * vector-valued finite elements. + * Given a FEValuesBase object, extract the second derivatives on the + * present cell from the vector we actually store. This function does + * the same as the one above but for vector-valued finite elements. */ virtual void @@ -175,100 +147,89 @@ namespace internal std::vector > > &patch_hessians_system) const = 0; /** - * Clear all references to the - * vectors. + * Clear all references to the vectors. */ virtual void clear () = 0; /** - * Determine an estimate for - * the memory consumption (in - * bytes) of this object. + * Determine an estimate for the memory consumption (in bytes) of this + * object. */ virtual std::size_t memory_consumption () const = 0; /** - * Names of the components of this - * data vector. + * Pointer to the DoFHandler object that the vector is based on. + */ + SmartPointer dof_handler; + + /** + * Names of the components of this data vector. */ const std::vector names; /** - * A vector that for each of the - * n_output_variables variables of - * the current data set indicates - * whether they are scalar fields, - * parts of a vector-field, or any of - * the other supported kinds of data. + * A vector that for each of the n_output_variables variables of the + * current data set indicates whether they are scalar fields, parts of a + * vector-field, or any of the other supported kinds of data. */ const std::vector data_component_interpretation; /** - * Pointer to a DataPostprocessing - * object which shall be applied to - * this data vector. + * Pointer to a DataPostprocessing object which shall be applied to this + * data vector. */ SmartPointer > postprocessor; /** - * Number of output variables this - * dataset provides (either number of - * components in vector valued function - * / data vector or number of computed - * quantities, if DataPostprocessor is - * applied). This variable is - * determined via and thus equivalent - * to names.size(). + * Number of output variables this dataset provides (either number of + * components in vector valued function / data vector or number of + * computed quantities, if DataPostprocessor is applied). This variable + * is determined via and thus equivalent to names.size(). */ unsigned int n_output_variables; }; /** - * A data structure that holds - * all data needed in one thread - * when building patches in - * parallel. These data - * structures are created - * globally rather than on each - * cell to avoid allocation of - * memory in the threads. This is - * a base class for the - * AdditionalData kind of data - * structure discussed in the - * documentation of the - * WorkStream class. + * A data structure that holds all data needed in one thread when building + * patches in parallel. These data structures are created globally rather + * than on each cell to avoid allocation of memory in the threads. This is + * a base class for the AdditionalData kind of data structure discussed in + * the documentation of the WorkStream class. * - * The - * cell_to_patch_index_map - * is an array that stores for index - * [i][j] the number of the - * patch that associated with the cell - * with index @p j on level @p i. This - * information is set up prior to - * generation of the patches, and is - * needed to generate neighborship + * The cell_to_patch_index_map is an array that stores for + * index [i][j] the number of the patch that associated with the + * cell with index @p j on level @p i. This information is set up prior to + * generation of the patches, and is needed to generate neighborship * information. * - * This structure is used by - * several of the DataOut* - * classes, which derived their - * own ParallelData classes from - * it for additional fields. + * This structure is used by several of the DataOut* classes, which + * derived their own ParallelData classes from it for additional fields. */ template struct ParallelDataBase { - template - ParallelDataBase (const unsigned int n_components, - const unsigned int n_datasets, + ParallelDataBase (const unsigned int n_datasets, const unsigned int n_subdivisions, - const unsigned int n_q_points, const std::vector &n_postprocessor_outputs, - const FE &finite_elements); + const Mapping &mapping, + const std::vector > > &finite_elements, + const UpdateFlags update_flags, + const bool use_face_values); + + ParallelDataBase (const ParallelDataBase &data); + + template + void reinit_all_fe_values(std::vector > > &dof_data, + const typename dealii::Triangulation::cell_iterator &cell, + const unsigned int face = numbers::invalid_unsigned_int); + + const FEValuesBase & + get_present_fe_values(const unsigned int dataset) const; + + void resize_system_vectors(const unsigned int n_components); - const unsigned int n_components; const unsigned int n_datasets; const unsigned int n_subdivisions; @@ -280,36 +241,30 @@ namespace internal std::vector > > patch_hessians_system; std::vector > > postprocessed_values; - const dealii::hp::FECollection fe_collection; + const dealii::hp::MappingCollection mapping_collection; + const std::vector > > finite_elements; + const UpdateFlags update_flags; + + std::vector > > x_fe_values; + std::vector > > x_fe_face_values; }; /** - * A derived class for use in the - * DataOut class. This is - * a class for the - * AdditionalData kind of data - * structure discussed in the - * documentation of the - * WorkStream context. + * A derived class for use in the DataOut class. This is a class for the + * AdditionalData kind of data structure discussed in the documentation of + * the WorkStream context. */ template struct ParallelData : public ParallelDataBase { - template - ParallelData (const Quadrature &quadrature, - const unsigned int n_components, - const unsigned int n_datasets, + ParallelData (const unsigned int n_datasets, const unsigned int n_subdivisions, const std::vector &n_postprocessor_outputs, const Mapping &mapping, - const std::vector > &cell_to_patch_index_map, - const FE &finite_elements, - const UpdateFlags update_flags); - - const dealii::hp::QCollection q_collection; - const dealii::hp::MappingCollection mapping_collection; - dealii::hp::FEValues x_fe_values; + const std::vector > > &finite_elements, + const UpdateFlags update_flags, + const std::vector > &cell_to_patch_index_map); std::vector > patch_evaluation_points; @@ -322,21 +277,24 @@ namespace internal //TODO: Most of the documentation of DataOut_DoFData applies to DataOut. /** - * This is an abstract class which provides the functionality to - * generate patches for output by base classes from data vectors on a - * grid. It allows to store a pointer to a DoFHandler object and one - * or more pointers to node and cell data denoting functions on the - * grid which shall later be written in any of the implemented data - * formats. + * This is an abstract class which provides the functionality to generate + * patches for output by base classes from data vectors on a grid. It allows + * to store one or more pointers to a DoFHandler and attached node and cell + * data denoting functions on the grid which shall later be written in any of + * the implemented data formats. * * *

      User visible interface

      * - * The user visible interface of this class consists of functions which allow - * a user to make a DoFHandler object known to this class and to add data - * vectors which will later be written to a file in some format. Instead of - * pondering about the different functions, an example is probably the best - * way: + * The user visible interface of this class allows the user to specify data in + * two different ways. One is to make a DoFHandler object known to this class + * and to add data vectors that all correspond to this DoFHandler or the grid + * cells which will later be written to a file in some format. The second + * approach is to pass a DoFHandler object along with the vector. This allows + * setting data from different DoFHandlers in a neat way (of course, they both + * need to be based on the same triangulation). Instead of pondering about the + * different functions, an example for the first kind is probably the best + * explanation: * @code * ... * ... // compute solution, which contains nodal values @@ -399,7 +357,7 @@ namespace internal * function build_patches(). Finally, you write() the data in one format or other, * to a file. * - * Please note, that in the example above, an object of type DataOut was + * Please note that in the example above, an object of type DataOut was * used, i.e. an object of a derived class. This is necessary since this * class does not provide means to actually generate the patches, only aids to * store and access data. @@ -470,45 +428,31 @@ class DataOut_DoFData : public DataOutInterface public: /** - * Typedef to the iterator type - * of the dof handler class under + * Typedef to the iterator type of the dof handler class under * consideration. */ - typedef typename DH::cell_iterator cell_iterator; - typedef typename DH::active_cell_iterator active_cell_iterator; + typedef typename Triangulation::cell_iterator cell_iterator; + typedef typename Triangulation::active_cell_iterator active_cell_iterator; public: /** - * Type describing what the - * vector given to - * add_data_vector() is: a - * vector that has one entry per - * degree of freedom in a - * DoFHandler object (such - * as solution vectors), or one - * entry per cell in the - * triangulation underlying the - * DoFHandler object (such - * as error per cell data). The - * value #type_automatic tells - * add_data_vector() to find - * out itself (see the - * documentation of - * add_data_vector() for the - * method used). + * Type describing what the vector given to add_data_vector() is: a vector + * that has one entry per degree of freedom in a DoFHandler object (such as + * solution vectors), or one entry per cell in the triangulation underlying + * the DoFHandler object (such as error per cell data). The value + * #type_automatic tells add_data_vector() to find out itself (see the + * documentation of add_data_vector() for the method used). */ enum DataVectorType { /** - * Data vector entries are - * associated to degrees of freedom + * Data vector entries are associated to degrees of freedom */ type_dof_data, /** - * Data vector entries are one per - * grid cell + * Data vector entries are one per grid cell */ type_cell_data, @@ -529,140 +473,92 @@ public: virtual ~DataOut_DoFData (); /** - * Designate a dof handler to be - * used to extract geometry data - * and the mapping between nodes - * and node values. + * Designate a dof handler to be used to extract geometry data and the + * mapping between nodes and node values. This call is not necessary if all + * added data vectors are supplemented with a DoFHandler argument. + * + * This call is optional: If you add data vectors with specified DoFHandler + * object, then that contains all information needed to generate the output. */ void attach_dof_handler (const DH &); /** - * Add a data vector together - * with its name. + * Designate a triangulation to be used to extract geometry data and the + * mapping between nodes and node values. * - * A pointer to the vector is - * stored, so you have to make - * sure the vector exists at that - * address at least as long as - * you call the write_* + * This call is optional: If you add data vectors with specified DoFHandler + * object, then that contains all information needed to generate the + * output. This call is useful when you only output cell vectors and no + * DoFHandler at all, in which case it provides the geometry. + */ + void attach_triangulation (const Triangulation &); + + /** + * Add a data vector together with its name. + * + * A pointer to the vector is stored, so you have to make sure the vector + * exists at that address at least as long as you call the write_* * functions. * - * It is assumed that the vector - * has the same number of - * components as there are - * degrees of freedom in the dof - * handler, in which case it is - * assumed to be a vector storing - * nodal data; or the size may be - * the number of active cells on - * the present grid, in which - * case it is assumed to be a - * cell data vector. As the - * number of degrees of freedom - * and of cells is usually not - * equal, the function can - * determine itself which type of - * vector it is given. However, - * there are corner cases where - * this automatic determination - * does not work. One example is - * if you compute with piecewise - * constant elements and have a - * scalar solution, then there - * are as many cells as there are - * degrees of freedom (though - * they may be numbered - * differently). Another - * possibility is if you have a - * 1d mesh embedded in 2d space - * and the mesh consists of a - * closed curve of cells; in this - * case, there are as many nodes - * as there are cells, and when - * using a Q1 element you will - * have as many degrees of - * freedom as there are cells. - * In these cases, you can change - * the last argument of the - * function from its default - * value #type_automatic to - * either #type_dof_data or - * #type_cell_data, depending on - * what the vector - * represents. Apart from such - * corner cases, you can leave - * the argument at its default - * value and let the function - * determine the type of the - * vector itself. + * It is assumed that the vector has the same number of components as there + * are degrees of freedom in the dof handler, in which case it is assumed to + * be a vector storing nodal data; or the size may be the number of active + * cells on the present grid, in which case it is assumed to be a cell data + * vector. As the number of degrees of freedom and of cells is usually not + * equal, the function can determine itself which type of vector it is + * given. However, there are corner cases where this automatic determination + * does not work. One example is if you compute with piecewise constant + * elements and have a scalar solution, then there are as many cells as + * there are degrees of freedom (though they may be numbered + * differently). Another possibility is if you have a 1d mesh embedded in 2d + * space and the mesh consists of a closed curve of cells; in this case, + * there are as many nodes as there are cells, and when using a Q1 element + * you will have as many degrees of freedom as there are cells. In these + * cases, you can change the last argument of the function from its default + * value #type_automatic to either #type_dof_data or #type_cell_data, + * depending on what the vector represents. Apart from such corner cases, + * you can leave the argument at its default value and let the function + * determine the type of the vector itself. * - * If it is a vector holding DoF - * data, the names given shall be - * one for each component of the - * underlying finite element. If - * it is a finite element - * composed of only one - * subelement, then there is - * another function following - * which takes a single name - * instead of a vector of names. + * If it is a vector holding DoF data, the names given shall be one for each + * component of the underlying finite element. If it is a finite element + * composed of only one subelement, then there is another function following + * which takes a single name instead of a vector of names. * - * The data_component_interpretation - * argument contains information about - * how the individual components of - * output files that consist of more than - * one data set are to be interpreted. + * The data_component_interpretation argument contains information about how + * the individual components of output files that consist of more than one + * data set are to be interpreted. * - * For example, if one has a finite - * element for the Stokes equations in - * 2d, representing components (u,v,p), - * one would like to indicate that the - * first two, u and v, represent a - * logical vector so that later on when - * we generate graphical output we can - * hand them off to a visualization - * program that will automatically know - * to render them as a vector field, - * rather than as two separate and - * independent scalar fields. + * For example, if one has a finite element for the Stokes equations in 2d, + * representing components (u,v,p), one would like to indicate that the + * first two, u and v, represent a logical vector so that later on when we + * generate graphical output we can hand them off to a visualization program + * that will automatically know to render them as a vector field, rather + * than as two separate and independent scalar fields. * - * The default value of this argument - * (i.e. an empty vector) corresponds is + * The default value of this argument (i.e. an empty vector) corresponds is * equivalent to a vector of values - * DataComponentInterpretation::component_is_scalar, - * indicating that all output components - * are independent scalar - * fields. However, if the given data - * vector represents logical vectors, you - * may pass a vector that contains values - * DataComponentInterpretation::component_is_part_of_vector. In - * the example above, one would pass in a - * vector with components + * DataComponentInterpretation::component_is_scalar, indicating that all + * output components are independent scalar fields. However, if the given + * data vector represents logical vectors, you may pass a vector that + * contains values + * DataComponentInterpretation::component_is_part_of_vector. In the example + * above, one would pass in a vector with components * (DataComponentInterpretation::component_is_part_of_vector, * DataComponentInterpretation::component_is_part_of_vector, - * DataComponentInterpretation::component_is_scalar) - * for (u,v,p). + * DataComponentInterpretation::component_is_scalar) for (u,v,p). * - * The names of a data vector - * shall only contain characters - * which are letters, underscore - * and a few other ones. Refer to - * the ExcInvalidCharacter - * exception declared in this - * class to see which characters - * are valid and which are not. + * The names of a data vector shall only contain characters which are + * letters, underscore and a few other ones. Refer to the + * ExcInvalidCharacter exception declared in this class to see which + * characters are valid and which are not. * - * @note The actual type for the - * vector argument may be any - * vector type from which - * FEValues can extract values on - * a cell using the - * FEValuesBase::get_function_values() - * function. In particular, this - * includes all of the usual - * vector types, but also - * IndexSet (see step-41 for a - * use of this). + * @note The actual type for the vector argument may be any vector type from + * which FEValues can extract values on a cell using the + * FEValuesBase::get_function_values() function. In particular, this + * includes all of the usual vector types, but also IndexSet (see step-41 + * for a use of this). */ template void add_data_vector (const VECTOR &data, @@ -672,31 +568,19 @@ public: = std::vector()); /** - * This function is an abbreviation to - * the above one (see there for a - * discussion of the various arguments), - * intended for use with finite elements - * that are not composed of - * subelements. In this case, only one - * name per data vector needs to be - * given, which is what this function - * takes. It simply relays its arguments - * after a conversion of the @p name to a - * vector of strings, to the other - * add_data_vector() function above. + * This function is an abbreviation to the above one (see there for a + * discussion of the various arguments), intended for use with finite + * elements that are not composed of subelements. In this case, only one + * name per data vector needs to be given, which is what this function + * takes. It simply relays its arguments after a conversion of the @p name + * to a vector of strings, to the other add_data_vector() function above. * - * If @p data is a vector with - * multiple components this - * function will generate - * distinct names for all - * components by appending an - * underscore and the number of - * each component to @p name + * If @p data is a vector with multiple components this function will + * generate distinct names for all components by appending an underscore and + * the number of each component to @p name * - * The actual type for the template - * argument may be any vector type from - * which FEValues can extract values - * on a cell using the + * The actual type for the template argument may be any vector type from + * which FEValues can extract values on a cell using the * FEValuesBase::get_function_values() function. */ template @@ -707,158 +591,147 @@ public: = std::vector()); /** - * This function is an alternative to the - * above ones, allowing the output of - * derived quantities instead of the given - * data. This converison has to be done in - * a class derived from DataPostprocessor. + * This function is an extension of the above one (see there for a + * discussion of the arguments except the first one) and allows to set a + * vector with its own DoFHandler object. This DoFHandler needs to be + * compatible with the other DoFHandler objects assigned with calls to @p + * add_data_vector or @p attach_dof_handler, in the sense that the + * DoFHandler objects need to be based on the same triangulation. This + * function allows you to export data from multiple DoFHandlers that + * describe different solution components. + * + * Since this function takes a DoFHandler object and hence naturally + * represents dof data, the data vector type argument present in the other + * methods above is skipped. + */ + template + void add_data_vector (const DH &dof_handler, + const VECTOR &data, + const std::vector &names, + const std::vector &data_component_interpretation + = std::vector()); + + + /** + * This function is an abbreviation of the function above with only a scalar + * @p dof_handler given and a single data name. + */ + template + void add_data_vector (const DH &dof_handler, + const VECTOR &data, + const std::string &name, + const std::vector &data_component_interpretation + = std::vector()); + + /** + * This function is an alternative to the above ones, allowing the output of + * derived quantities instead of the given data. This converison has to be + * done in a class derived from DataPostprocessor. * - * The names for these derived quantities - * are provided by the @p - * data_postprocessor argument. Likewise, - * the data_component_interpretation - * argument of the other - * add_data_vector() functions is - * provided by the data_postprocessor - * argument. As only data of type @p - * type_dof_data can be transformed, this - * type is also known implicitly and does - * not have to be given. + * The names for these derived quantities are provided by the @p + * data_postprocessor argument. Likewise, the data_component_interpretation + * argument of the other add_data_vector() functions is provided by the + * data_postprocessor argument. As only data of type @p type_dof_data can be + * transformed, this type is also known implicitly and does not have to be + * given. * - * @note The actual type for the - * vector argument may be any - * vector type from which - * FEValues can extract values on - * a cell using the - * FEValuesBase::get_function_values() - * function. In particular, this - * includes all of the usual - * vector types, but also - * IndexSet (see step-41 for a - * use of this). + * @note The actual type for the vector argument may be any vector type from + * which FEValues can extract values on a cell using the + * FEValuesBase::get_function_values() function. In particular, this + * includes all of the usual vector types, but also IndexSet (see step-41 + * for a use of this). */ template void add_data_vector (const VECTOR &data, const DataPostprocessor &data_postprocessor); /** - * Release the pointers to the - * data vectors. This allows - * output of a new set of vectors - * without supplying the DoF - * handler again. Therefore, the - * DataOut object can be used - * in an algebraic context. Note - * that besides the data vectors - * also the patches already - * computed are deleted. + * Same function as above, but with a DoFHandler object that does not need + * to coincide with the DoFHandler initially set. Note that the + * postprocessor can only read data from the given DoFHandler and solution + * vector, not other solution vectors or DoFHandlers. + */ + template + void add_data_vector (const DH &dof_handler, + const VECTOR &data, + const DataPostprocessor &data_postprocessor); + + /** + * Release the pointers to the data vectors. This allows output of a new set + * of vectors without supplying the DoF handler again. Therefore, the + * DataOut object can be used in an algebraic context. Note that besides the + * data vectors also the patches already computed are deleted. */ void clear_data_vectors (); /** - * Release pointers to all input - * data elements, i.e. pointers - * to data vectors and to the DoF - * handler object. This function - * may be useful when you have - * called the @p build_patches - * function of derived class, - * since then the patches are - * built and the input data is no - * more needed, nor is there a - * need to reference it. You can - * then output the patches - * detached from the main thread - * and need not make sure anymore - * that the DoF handler object - * and vectors must not be - * deleted before the output - * thread is finished. + * Release pointers to all input data elements, i.e. pointers to data + * vectors and to the DoF handler object. This function may be useful when + * you have called the @p build_patches function of derived class, since + * then the patches are built and the input data is no more needed, nor is + * there a need to reference it. You can then output the patches detached + * from the main thread and need not make sure anymore that the DoF handler + * object and vectors must not be deleted before the output thread is + * finished. */ void clear_input_data_references (); /** - * This function can be used to - * merge the patches that were - * created using the - * @p build_patches function of - * the object given as argument - * into the list of patches - * created by this object. This - * is sometimes handy if one has, - * for example, a domain - * decomposition algorithm where - * each block is represented by a - * DoFHandler of its own, - * but one wants to output the - * solution on all the blocks at - * the same time. + * This function can be used to merge the patches that were created using + * the @p build_patches function of the object given as argument into the + * list of patches created by this object. This is sometimes handy if one + * has, for example, a domain decomposition algorithm where each block is + * represented by a DoFHandler of its own, but one wants to output the + * solution on all the blocks at the same time. * - * For this to work, the given - * argument and this object need - * to have the same number of - * output vectors, and they need - * to use the same number of - * subdivisions per patch. The - * output will probably look - * rather funny if patches in - * both objects overlap in space. + * For this to work, the given argument and this object need to have the + * same number of output vectors, and they need to use the same number of + * subdivisions per patch. The output will probably look rather funny if + * patches in both objects overlap in space. * - * If you call - * build_patches() for this - * object after merging in - * patches, the previous state is - * overwritten, and the merged-in - * patches are lost. + * If you call build_patches() for this object after merging in patches, the + * previous state is overwritten, and the merged-in patches are lost. * - * The second parameter allows to - * shift each node of the patches - * in the object passed in in the - * first parameter by a certain - * amount. This is sometimes - * useful to generate "exploded" - * views of a collection of - * blocks. + * The second parameter allows to shift each node of the patches in the + * object passed in in the first parameter by a certain amount. This is + * sometimes useful to generate "exploded" views of a collection of blocks. * - * This function will fail if - * either this or the other - * object did not yet set up any - * patches. + * This function will fail if either this or the other object did not yet + * set up any patches. */ template void merge_patches (const DataOut_DoFData &source, const Point &shift = Point()); /** - * Release the pointers to the - * data vectors and the DoF - * handler. You have to set all - * data entries again using the - * add_data_vector() - * function. The pointer to the - * dof handler is cleared as - * well, along with all other - * data. In effect, this function - * resets everything to a virgin - * state. + * Release the pointers to the data vectors and the DoF handler. You have to + * set all data entries again using the add_data_vector() function. The + * pointer to the dof handler is cleared as well, along with all other + * data. In effect, this function resets everything to a virgin state. */ virtual void clear (); /** - * Determine an estimate for the - * memory consumption (in bytes) - * of this object. + * Determine an estimate for the memory consumption (in bytes) of this + * object. */ std::size_t memory_consumption () const; + /** + * Exception + */ + DeclException0 (ExcNoTriangulationSelected); + /** * Exception */ DeclException0 (ExcNoDoFHandlerSelected); + /** * Exception */ DeclException0 (ExcDataPostprocessingIsNotPossibleForCellData); + /** * Exception */ @@ -917,69 +790,69 @@ public: protected: /** - * Abbreviate the somewhat lengthy - * name for the Patch class. + * Abbreviate the somewhat lengthy name for the Patch class. */ typedef dealii::DataOutBase::Patch Patch; /** - * Pointer to the dof handler object. + * Pointer to the triangulation object. + */ + SmartPointer > triangulation; + + /** + * Pointer to the optional handler object. */ - SmartPointer > dofs; + SmartPointer dofs; /** - * List of data elements with vectors of - * values for each degree of freedom. + * List of data elements with vectors of values for each degree of freedom. */ std::vector > > dof_data; /** - * List of data elements with vectors of - * values for each cell. + * List of data elements with vectors of values for each cell. */ std::vector > > cell_data; /** - * This is a list of patches that is - * created each time build_patches() - * is called. These patches are used - * in the output routines of the base + * This is a list of patches that is created each time build_patches() is + * called. These patches are used in the output routines of the base * classes. */ std::vector patches; /** - * Function by which the base - * class's functions get to know - * what patches they shall write - * to a file. + * Function by which the base class's functions get to know what patches + * they shall write to a file. */ virtual const std::vector &get_patches () const; /** - * Virtual function through - * which the names of data sets are - * obtained by the output functions - * of the base class. + * Virtual function through which the names of data sets are obtained by the + * output functions of the base class. */ virtual std::vector get_dataset_names () const; /** - * Overload of the respective - * DataOutInterface::get_vector_data_ranges() - * function. See there for a more - * extensive documentation. + * Extracts the finite elements stored in the dof_data object, including a + * dummy object of FE_DGQ(0) in case only the triangulation is used. + */ + std::vector > > + get_finite_elements() const; + + /** + * Overload of the respective DataOutInterface::get_vector_data_ranges() + * function. See there for a more extensive documentation. */ virtual std::vector > get_vector_data_ranges () const; /** - * Make all template siblings - * friends. Needed for the - * merge_patches() function. + * Make all template siblings friends. Needed for the merge_patches() + * function. */ template friend class DataOut_DoFData; @@ -988,6 +861,9 @@ protected: /** + * This class is the main class to provide output of data described by finite + * element fields defined on a collection of cells. + * * This class is an actual implementation of the functionality proposed by * the DataOut_DoFData class. It offers a function build_patches() that * generates the patches to be written in some graphics format from the data @@ -1072,17 +948,15 @@ class DataOut : public DataOut_DoFData { public: /** - * Typedef to the iterator type - * of the dof handler class under + * Typedef to the iterator type of the dof handler class under * consideration. */ typedef typename DataOut_DoFData::cell_iterator cell_iterator; typedef typename DataOut_DoFData::active_cell_iterator active_cell_iterator; /** - * Enumeration describing the region of the - * domain in which curved cells shall be - * created. + * Enumeration describing the region of the domain in which curved cells + * shall be created. */ enum CurvedCellRegion { @@ -1092,108 +966,61 @@ public: }; /** - * This is the central function - * of this class since it builds - * the list of patches to be - * written by the low-level - * functions of the base - * class. See the general - * documentation of this class - * for further information. + * This is the central function of this class since it builds the list of + * patches to be written by the low-level functions of the base class. See + * the general documentation of this class for further information. * - * The default value 0 - * of n_subdivisions - * indicates that the value - * stored in - * DataOutInterface::default_subdivisions - * is to be used. + * The default value 0 of n_subdivisions indicates that + * the value stored in DataOutInterface::default_subdivisions is to be used. */ virtual void build_patches (const unsigned int n_subdivisions = 0); /** - * Same as above, except that the - * additional first parameter - * defines a mapping that is to - * be used in the generation of - * output. If - * n_subdivisions>1, the - * points interior of subdivided - * patches which originate from - * cells at the boundary of the - * domain can be computed using the - * mapping, i.e. a higher order - * mapping leads to a - * representation of a curved - * boundary by using more - * subdivisions. Some mappings like - * MappingQEulerian result in curved cells - * in the interior of the domain. However, - * there is nor easy way to get this - * information from the Mapping. Thus the - * last argument @p curved_region take one - * of three values resulting in no curved - * cells at all, curved cells at the - * boundary (default) or curved cells in - * the whole domain. + * Same as above, except that the additional first parameter defines a + * mapping that is to be used in the generation of output. If + * n_subdivisions>1, the points interior of subdivided patches + * which originate from cells at the boundary of the domain can be computed + * using the mapping, i.e. a higher order mapping leads to a representation + * of a curved boundary by using more subdivisions. Some mappings like + * MappingQEulerian result in curved cells in the interior of the + * domain. However, there is nor easy way to get this information from the + * Mapping. Thus the last argument @p curved_region take one of three values + * resulting in no curved cells at all, curved cells at the boundary + * (default) or curved cells in the whole domain. * - * Even for non-curved cells the - * mapping argument can be used - * for the Eulerian mappings (see - * class MappingQ1Eulerian) where - * a mapping is used not only to - * determine the position of - * points interior to a cell, but - * also of the vertices. It - * offers an opportunity to watch - * the solution on a deformed - * triangulation on which the - * computation was actually - * carried out, even if the mesh - * is internally stored in its - * undeformed configuration and - * the deformation is only - * tracked by an additional - * vector that holds the + * Even for non-curved cells the mapping argument can be used for the + * Eulerian mappings (see class MappingQ1Eulerian) where a mapping is used + * not only to determine the position of points interior to a cell, but also + * of the vertices. It offers an opportunity to watch the solution on a + * deformed triangulation on which the computation was actually carried out, + * even if the mesh is internally stored in its undeformed configuration and + * the deformation is only tracked by an additional vector that holds the * deformation of each vertex. * - * @todo The @p mapping argument should be - * replaced by a hp::MappingCollection in - * case of a hp::DoFHandler. + * @todo The @p mapping argument should be replaced by a + * hp::MappingCollection in case of a hp::DoFHandler. */ virtual void build_patches (const Mapping &mapping, const unsigned int n_subdivisions = 0, const CurvedCellRegion curved_region = curved_boundary); /** - * Return the first cell which we - * want output for. The default - * implementation returns the - * first active cell, but you - * might want to return other - * cells in a derived class. + * Return the first cell which we want output for. The default + * implementation returns the first active cell, but you might want to + * return other cells in a derived class. */ virtual cell_iterator first_cell (); /** - * Return the next cell after - * @p cell which we want output - * for. If there are no more - * cells, #dofs->end() shall - * be returned. + * Return the next cell after @p cell which we want output for. If there + * are no more cells, #dofs->end() shall be returned. * - * The default implementation - * returns the next active cell, - * but you might want to return - * other cells in a derived - * class. Note that the default - * implementation assumes that - * the given @p cell is active, - * which is guaranteed as long as - * first_cell() is also used - * from the default - * implementation. Overloading - * only one of the two functions - * might not be a good idea. + * The default implementation returns the next active cell, but you might + * want to return other cells in a derived class. Note that the default + * implementation assumes that the given @p cell is active, which is + * guaranteed as long as first_cell() is also used from the default + * implementation. Overloading only one of the two functions might not be a + * good idea. */ virtual cell_iterator next_cell (const cell_iterator &cell); @@ -1208,36 +1035,23 @@ public: private: /** - * Return the first cell produced - * by the - * first_cell()/next_cell() - * function pair that is locally - * owned. If this object operates - * on a non-distributed - * triangulation, the result - * equals what first_cell() - * returns. + * Return the first cell produced by the first_cell()/next_cell() function + * pair that is locally owned. If this object operates on a non-distributed + * triangulation, the result equals what first_cell() returns. */ cell_iterator first_locally_owned_cell (); /** - * Return the next cell produced - * by the next_cell() function - * that is locally owned. If this - * object operates on a - * non-distributed triangulation, - * the result equals what - * first_cell() returns. + * Return the next cell produced by the next_cell() function that is locally + * owned. If this object operates on a non-distributed triangulation, the + * result equals what first_cell() returns. */ cell_iterator next_locally_owned_cell (const cell_iterator &cell); /** - * Build one patch. This function - * is called in a WorkStream - * context. + * Build one patch. This function is called in a WorkStream context. * - * The result is written into the patch - * variable. + * The result is written into the patch variable. */ void build_one_patch (const std::pair *cell_and_index, internal::DataOut::ParallelData &data, @@ -1250,49 +1064,6 @@ private: // -------------------- template and inline functions ------------------------ -namespace internal -{ - namespace DataOut - { - template - template - ParallelDataBase:: - ParallelDataBase (const unsigned int n_components, - const unsigned int n_datasets, - const unsigned int n_subdivisions, - const unsigned int n_q_points, - const std::vector &n_postprocessor_outputs, - const FE &finite_elements) - : - n_components (n_components), - n_datasets (n_datasets), - n_subdivisions (n_subdivisions), - patch_values (n_q_points), - patch_values_system (n_q_points), - patch_gradients (n_q_points), - patch_gradients_system (n_q_points), - patch_hessians (n_q_points), - patch_hessians_system (n_q_points), - postprocessed_values (n_postprocessor_outputs.size()), - fe_collection (finite_elements) - { - for (unsigned int k=0; k(n_postprocessor_outputs[dataset])); - } - } -} - - template template void diff --git a/deal.II/include/deal.II/numerics/data_out_faces.h b/deal.II/include/deal.II/numerics/data_out_faces.h index 07c33fd264..defebb091e 100644 --- a/deal.II/include/deal.II/numerics/data_out_faces.h +++ b/deal.II/include/deal.II/numerics/data_out_faces.h @@ -43,20 +43,13 @@ namespace internal template struct ParallelData : public internal::DataOut::ParallelDataBase { - template - ParallelData (const Quadrature &quadrature, - const unsigned int n_components, - const unsigned int n_datasets, + ParallelData (const unsigned int n_datasets, const unsigned int n_subdivisions, const std::vector &n_postprocessor_outputs, const Mapping &mapping, - const FE &finite_elements, + const std::vector > > &finite_elements, const UpdateFlags update_flags); - const dealii::hp::QCollection q_collection; - const dealii::hp::MappingCollection mapping_collection; - dealii::hp::FEFaceValues x_fe_values; - std::vector > patch_normals; std::vector > patch_evaluation_points; }; diff --git a/deal.II/include/deal.II/numerics/data_out_rotation.h b/deal.II/include/deal.II/numerics/data_out_rotation.h index 95f4f57378..1a45fd3fbb 100644 --- a/deal.II/include/deal.II/numerics/data_out_rotation.h +++ b/deal.II/include/deal.II/numerics/data_out_rotation.h @@ -43,21 +43,16 @@ namespace internal template struct ParallelData : public internal::DataOut::ParallelDataBase { - template - ParallelData (const Quadrature &quadrature, - const unsigned int n_components, - const unsigned int n_datasets, + ParallelData (const unsigned int n_datasets, const unsigned int n_subdivisions, const unsigned int n_patches_per_circle, const std::vector &n_postprocessor_outputs, - const FE &finite_elements, + const Mapping &mapping, + const std::vector > > &finite_elements, const UpdateFlags update_flags); const unsigned int n_patches_per_circle; - const dealii::hp::QCollection q_collection; - dealii::hp::FEValues x_fe_values; - std::vector > patch_evaluation_points; }; } diff --git a/deal.II/include/deal.II/numerics/data_postprocessor.h b/deal.II/include/deal.II/numerics/data_postprocessor.h index 0473525720..0260969acc 100644 --- a/deal.II/include/deal.II/numerics/data_postprocessor.h +++ b/deal.II/include/deal.II/numerics/data_postprocessor.h @@ -82,7 +82,7 @@ DEAL_II_NAMESPACE_OPEN * takes a solution that consists of velocity, pressure and temperature (dim+2 * components) and computes a variety of output quantities, some of which * are vector valued and some of which are scalar. On the other hand, - * in step-28 we implement a postprocessor that only computes the magnitude + * in step-29 we implement a postprocessor that only computes the magnitude * of a complex number given by a two-component finite element. It seems silly * to have to implement four virtual functions for this * (compute_derived_quantities_scalar() or compute_derived_quantities_vector(), diff --git a/deal.II/include/deal.II/numerics/vector_tools.h b/deal.II/include/deal.II/numerics/vector_tools.h index 96fd9a1b7c..d7cf41a6ed 100644 --- a/deal.II/include/deal.II/numerics/vector_tools.h +++ b/deal.II/include/deal.II/numerics/vector_tools.h @@ -182,7 +182,7 @@ class ConstraintMatrix; * *
    • Creation of right hand side vectors for point sources: * The create_point_source_vector() function computes the vector - * $f_i = \int_\Omega \delta_0(x-x_0) \phi_i(x) dx$. + * $f_i = \int_\Omega \delta(x-x_0) \phi_i(x) dx$. * *
    • Creation of boundary right hand side vectors: The * create_boundary_right_hand_side() function computes the vector @@ -1785,7 +1785,9 @@ namespace VectorTools /** * Create a right hand side - * vector for a point source at point @p p. + * vector for a point source at point @p p. In other words, it creates + * a vector $F$ so that + * $F_i = \int_\Omega \delta(x-p) \phi_i(x) dx$. * Prior content of the * given @p rhs_vector vector is * deleted. diff --git a/deal.II/source/base/data_out_base.cc b/deal.II/source/base/data_out_base.cc index 1638903344..7277a8520d 100644 --- a/deal.II/source/base/data_out_base.cc +++ b/deal.II/source/base/data_out_base.cc @@ -2194,10 +2194,12 @@ DataOutBase::TecplotFlags::memory_consumption () const DataOutBase::VtkFlags::VtkFlags (const double time, - const unsigned int cycle) + const unsigned int cycle, + const bool print_date_and_time) : time (time), - cycle (cycle) + cycle (cycle), + print_date_and_time (print_date_and_time) {} @@ -4945,14 +4947,18 @@ DataOutBase::write_vtk (const std::vector > &patches, std::tm *time = std::localtime(&time1); out << "# vtk DataFile Version 3.0" << '\n' - << "#This file was generated by the deal.II library on " - << time->tm_year+1900 << "/" - << time->tm_mon+1 << "/" - << time->tm_mday << " at " - << time->tm_hour << ":" - << std::setw(2) << time->tm_min << ":" - << std::setw(2) << time->tm_sec - << '\n' + << "#This file was generated by the deal.II library"; + if (flags.print_date_and_time) + out << " on " + << time->tm_year+1900 << "/" + << time->tm_mon+1 << "/" + << time->tm_mday << " at " + << time->tm_hour << ":" + << std::setw(2) << time->tm_min << ":" + << std::setw(2) << time->tm_sec; + else + out << "."; + out << '\n' << "ASCII" << '\n'; // now output the data header @@ -5162,7 +5168,8 @@ DataOutBase::write_vtk (const std::vector > &patches, } -void DataOutBase::write_vtu_header (std::ostream &out) +void DataOutBase::write_vtu_header (std::ostream &out, + const VtkFlags &flags) { AssertThrow (out, ExcIO()); std::time_t time1= std::time (0); @@ -5171,15 +5178,18 @@ void DataOutBase::write_vtu_header (std::ostream &out) out << "\n"; - + << "#This file was generated by the deal.II library"; + if (flags.print_date_and_time) + out << " on " + << time->tm_year+1900 << "/" + << time->tm_mon+1 << "/" + << time->tm_mday << " at " + << time->tm_hour << ":" + << std::setw(2) << time->tm_min << ":" + << std::setw(2) << time->tm_sec; + else + out << "."; + out << "\n-->\n"; out << " > &patches, const VtkFlags &flags, std::ostream &out) { - write_vtu_header(out); + write_vtu_header(out, flags); write_vtu_main (patches, data_names, vector_data_ranges, flags, out); write_vtu_footer(out); @@ -6498,7 +6508,7 @@ void DataOutInterface::write_vtu_in_parallel (const char *filename if (myrank==0) { std::stringstream ss; - DataOutBase::write_vtu_header(ss); + DataOutBase::write_vtu_header(ss, vtk_flags); header_size = ss.str().size(); MPI_File_write(fh, const_cast(ss.str().c_str()), header_size, MPI_CHAR, NULL); } diff --git a/deal.II/source/base/geometry_info.cc b/deal.II/source/base/geometry_info.cc index b8223630f0..6569451117 100644 --- a/deal.II/source/base/geometry_info.cc +++ b/deal.II/source/base/geometry_info.cc @@ -1101,7 +1101,9 @@ unsigned int GeometryInfo<2>::child_cell_on_face (const RefinementCase<2> &ref_case, const unsigned int face, const unsigned int subface, - const bool, const bool face_flip, const bool, + const bool /*face_orientation*/, + const bool face_flip, + const bool /*face_rotation*/, const RefinementCase<1> &) { Assert (face(&*ranges.begin()), ranges.size() * sizeof(Range)); + + do_compress(); // needed so that largest_range can be recomputed } diff --git a/deal.II/source/base/logstream.cc b/deal.II/source/base/logstream.cc index ba7f8773f3..447ff34110 100644 --- a/deal.II/source/base/logstream.cc +++ b/deal.II/source/base/logstream.cc @@ -137,23 +137,65 @@ LogStream::operator<< (std::ostream& (*p) (std::ostream &)) // Print to the internal stringstream: stream << p; - // Next check whether this is the flush or endl - // manipulator, and if so print out the message. - std::ostream & (* const p_flush) (std::ostream &) = &std::flush; - std::ostream & (* const p_endl) (std::ostream &) = &std::endl; - if (p == p_flush || p == p_endl) + + // This is a bloody hack until LogStream got reimplemented as a proper + // child of std::streambuf (or similar). + // + // The problem is that at this point we would like to know whether an + // std::flush or std::endl has called us, however, there is no way to + // detect this in a sane manner. + // + // The obvious idea to compare function pointers, + // std::ostream & (* const p_flush) (std::ostream &) = &std::flush; + // p == p_flush ? ..., + // is wrong as there doesn't has to be a _single_ std::flush instance... + // there could be multiple of it. And in fact, LLVM's libc++ implements + // std::flush and std::endl in a way that every shared library and + // executable has its local copy... fun... + // + // - Maier, 2013 + + class QueryStreambuf : public std::streambuf + { + // Implement a minimalistic stream buffer that only stores the fact + // whether overflow or sync was called + public: + QueryStreambuf() + : flushed_(false), newline_written_(false) + { + } + bool flushed() { return flushed_; } + bool newline_written() { return newline_written_; } + private: + int_type overflow(int_type ch) + { + newline_written_ = true; + return ch; + } + int sync() + { + flushed_ = true; + return 0; + } + bool flushed_; + bool newline_written_; + } query_streambuf; + + { + // and initialize an ostream with this streambuf: + std::ostream inject (&query_streambuf); + inject << p; + } + + if (query_streambuf.flushed()) { Threads::Mutex::ScopedLock lock(write_lock); - // Print the line head in case of a newline: + // Print the line head in case of a previous newline: if (at_newline) print_line_head(); - if (p == p_flush) - at_newline = false; - - if (p == p_endl) - at_newline = true; + at_newline = query_streambuf.newline_written(); if (get_prefixes().size() <= std_depth) *std_out << stream.str(); @@ -161,7 +203,7 @@ LogStream::operator<< (std::ostream& (*p) (std::ostream &)) if (file && (get_prefixes().size() <= file_depth)) *file << stream.str() << std::flush; - // Start a new string + // Start a new string: stream.str(""); } diff --git a/deal.II/source/base/table_handler.cc b/deal.II/source/base/table_handler.cc index aed67bee63..831434c98d 100644 --- a/deal.II/source/base/table_handler.cc +++ b/deal.II/source/base/table_handler.cc @@ -343,25 +343,62 @@ void TableHandler::write_text(std::ostream &out, const unsigned int nrows = n_rows(); const unsigned int n_cols = sel_columns.size(); - // handle the simple format separately first - if (format==simple_table_with_separate_column_description) + // cache the columns and compute the widths of each column for alignment + std::vector cols; + std::vector column_widths (n_cols, 0); + for (unsigned int j=0; j::const_iterator + col_iter=columns.find(key); + Assert(col_iter!=columns.end(), ExcInternalError()); + cols.push_back(&(col_iter->second)); + + column_widths[j] = col_iter->second.max_length; + } + + switch (format) + { + case org_mode_table: { // write the captions + out << "| " << std::left; for (unsigned int j=0; j cols; + out << std::flush; + return; + } + + case simple_table_with_separate_column_description: + { + // write the captions for (unsigned int j=0; j::const_iterator - col_iter=columns.find(key); - Assert(col_iter!=columns.end(), ExcInternalError()); - cols.push_back(&(col_iter->second)); + const std::string &key = sel_columns[j]; + out << "# " << j+1 << ": " << key << '\n'; } // write the body @@ -380,33 +417,21 @@ void TableHandler::write_text(std::ostream &out, out << std::flush; return; } - - // cache the columns and compute the widths of each column for alignment - std::vector cols; - std::vector column_widths (n_cols, 0); - for (unsigned int j=0; j::const_iterator - col_iter=columns.find(key); - Assert(col_iter!=columns.end(), ExcInternalError()); - cols.push_back(&(col_iter->second)); - - column_widths[j] = col_iter->second.max_length; - } - - // writing the captions for table_with_separate_column_description - // means that we ignore supercolumns and output the column - // header for each column. enumerate columns starting with 1 - if (format == table_with_separate_column_description) + + case table_with_separate_column_description: { + // writing the captions for table_with_separate_column_description + // means that we ignore supercolumns and output the column + // header for each column. enumerate columns starting with 1 for (unsigned int j=0; jget_fe().dofs_per_face != 0) - || - (cell->neighbor(face)->get_fe().dofs_per_face != 0)) - { - Assert (cell->get_fe().dofs_per_face - == - cell->neighbor(face)->get_fe().dofs_per_face, - ExcNotImplemented()); - - // (ab)use the master and slave dofs arrays for - // a moment here - master_dofs.resize (cell->get_fe().dofs_per_face); - cell->face(face) - ->get_dof_indices (master_dofs, - cell->active_fe_index ()); - - slave_dofs.resize (cell->neighbor(face)->get_fe().dofs_per_face); - cell->face(face) - ->get_dof_indices (slave_dofs, - cell->neighbor(face)->active_fe_index ()); - - for (unsigned int i=0; iget_fe().dofs_per_face; ++i) - AssertDimension (master_dofs[i], slave_dofs[i]); - } - + // dominates the other. + // + // a final possibility is that we have something like + // FESystem(FE_Q(1),FE_Q(1)) vs + // FESystem(FE_Q(1),FE_Nothing()), see + // hp/fe_nothing_18/19. + // + // in any case, the point is that it doesn't + // matter. there is nothing to do here. break; } @@ -2792,6 +2768,12 @@ namespace DoFTools // to this particular child // // @precondition: face_1 is supposed to be active + // + // @note As bug #82 ((http://code.google.com/p/dealii/issues/detail?id=82) and the + // corresponding testcase bits/periodicity_05 demonstrate, we can occasionally + // get into trouble if we already have the constraint x1=x2 and want to insert + // x2=x1. we avoid this by skipping an identity constraint if the opposite + // constraint already exists template void set_periodicity_constraints (const FaceIterator &face_1, @@ -2897,21 +2879,83 @@ namespace DoFTools || component_mask[fe.face_system_to_component_index(i).first]) { - constraint_matrix.add_line(dofs_2[i]); + // as mentioned in the comment above this function, we need + // to be careful about treating identity constraints differently. + // consequently, find out whether this dof 'i' will be + // identity constrained + // + // to check whether this is the case, first see whether there are + // any weights other than 0 and 1, then in a first stage make sure + // that if so there is only one weight equal to 1 + bool is_identity_constrained = true; for (unsigned int jj=0; jj +unsigned int +FiniteElement:: +face_to_cell_index (const unsigned int face_index, + const unsigned int face, + const bool face_orientation, + const bool face_flip, + const bool face_rotation) const +{ + Assert (face_index < this->dofs_per_face, + ExcIndexRange(face_index, 0, this->dofs_per_face)); + Assert (face < GeometryInfo::faces_per_cell, + ExcIndexRange(face, 0, GeometryInfo::faces_per_cell)); + +//TODO: we could presumably solve the 3d case below using the +// adjust_quad_dof_index_for_face_orientation_table field. for the +// 2d case, we can't use adjust_line_dof_index_for_line_orientation_table +// since that array is empty (presumably because we thought that +// there are no flipped edges in 2d, but these can happen in +// DoFTools::make_periodicity_constraints, for example). so we +// would need to either fill this field, or rely on derived classes +// implementing this function, as we currently do + + // see the function's documentation for an explanation of this + // assertion -- in essence, derived classes have to implement + // an overloaded version of this function if we are to use any + // other than standard orientation + if ((face_orientation != true) || (face_flip != false) || (face_rotation != false)) + Assert ((this->dofs_per_line <= 1) && (this->dofs_per_quad <= 1), + ExcMessage ("The function in this base class can not handle this case. " + "Rather, the derived class you are using must provide " + "an overloaded version but apparently hasn't done so. See " + "the documentation of this function for more information.")); + + // we need to distinguish between DoFs on vertices, lines and in 3d quads. + // do so in a sequence of if-else statements + if (face_index < this->first_face_line_index) + // DoF is on a vertex + { + // get the number of the vertex on the face that corresponds to this DoF, + // along with the number of the DoF on this vertex + const unsigned int face_vertex = face_index / this->dofs_per_vertex; + const unsigned int dof_index_on_vertex = face_index % this->dofs_per_vertex; + + // then get the number of this vertex on the cell and translate + // this to a DoF number on the cell + return (GeometryInfo::face_to_cell_vertices(face, face_vertex, + face_orientation, + face_flip, + face_rotation) + * this->dofs_per_vertex + + + dof_index_on_vertex); + } + else if (face_index < this->first_face_quad_index) + // DoF is on a face + { + // do the same kind of translation as before. we need to only consider + // DoFs on the lines, i.e., ignoring those on the vertices + const unsigned int index = face_index - this->first_face_line_index; + + const unsigned int face_line = index / this->dofs_per_line; + const unsigned int dof_index_on_line = index % this->dofs_per_line; + + return (this->first_line_index + + GeometryInfo::face_to_cell_lines(face, face_line, + face_orientation, + face_flip, + face_rotation) + * this->dofs_per_line + + + dof_index_on_line); + } + else + // DoF is on a quad + { + Assert (dim >= 3, ExcInternalError()); + + // ignore vertex and line dofs + const unsigned int index = face_index - this->first_face_quad_index; + + return (this->first_quad_index + + face * this->dofs_per_quad + + index); + } +} + + + + template unsigned int FiniteElement::adjust_quad_dof_index_for_face_orientation (const unsigned int index, diff --git a/deal.II/source/fe/fe_data.cc b/deal.II/source/fe/fe_data.cc index e0873d9ba3..894e3c3f18 100644 --- a/deal.II/source/fe/fe_data.cc +++ b/deal.II/source/fe/fe_data.cc @@ -99,54 +99,6 @@ bool FiniteElementData::operator== (const FiniteElementData &f) const (conforming_space == f.conforming_space)); } -template -unsigned int -FiniteElementData:: -face_to_cell_index (const unsigned int face_index, - const unsigned int face, - const bool face_orientation, - const bool face_flip, - const bool face_rotation) const -{ - Assert (face_index < this->dofs_per_face, - ExcIndexRange(face_index, 0, this->dofs_per_face)); - Assert (face < GeometryInfo::faces_per_cell, - ExcIndexRange(face, 0, GeometryInfo::faces_per_cell)); - - // DoF on a vertex - if (face_index < this->first_face_line_index) - { - // Vertex number on the face - const unsigned int face_vertex = face_index / this->dofs_per_vertex; - return face_index % this->dofs_per_vertex - + GeometryInfo::face_to_cell_vertices(face, face_vertex, - face_orientation, - face_flip, - face_rotation) - * this->dofs_per_vertex; - } - // Else, DoF on a line? - if (face_index < this->first_face_quad_index) - { - // Ignore vertex dofs - const unsigned int index = face_index - this->first_face_line_index; - // Line number on the face - const unsigned int face_line = index / this->dofs_per_line; - return this->first_line_index + index % this->dofs_per_line - + GeometryInfo::face_to_cell_lines(face, face_line, - face_orientation, - face_flip, - face_rotation) - * this->dofs_per_line; - } - // Else, DoF is on a quad - - // Ignore vertex and line dofs - const unsigned int index = face_index - this->first_face_quad_index; - return this->first_quad_index + index - + face * this->dofs_per_quad; -} - template class FiniteElementData<1>; template class FiniteElementData<2>; diff --git a/deal.II/source/fe/fe_face.cc b/deal.II/source/fe/fe_face.cc index b8637568fc..bbf8124ada 100644 --- a/deal.II/source/fe/fe_face.cc +++ b/deal.II/source/fe/fe_face.cc @@ -17,15 +17,30 @@ #include #include +#include +#include #include DEAL_II_NAMESPACE_OPEN + +namespace +{ + std::vector > + get_QGaussLobatto_points (const unsigned int degree) + { + if (degree > 0) + return QGaussLobatto<1>(degree+1).get_points(); + else + return std::vector >(1, Point<1>(0.5)); + } +} + template FE_FaceQ::FE_FaceQ (const unsigned int degree) : FE_PolyFace, dim, spacedim> ( - TensorProductPolynomials(Polynomials::LagrangeEquidistant::generate_complete_basis(degree)), + TensorProductPolynomials(Polynomials::generate_complete_Lagrange_basis(get_QGaussLobatto_points(degree))), FiniteElementData(get_dpo_vector(degree), 1, degree, FiniteElementData::L2), std::vector(1,true)) { @@ -38,24 +53,44 @@ FE_FaceQ::FE_FaceQ (const unsigned int degree) this->unit_face_support_points[0][d] = 0.5; else { - const double step = 1./this->degree; - Point p; + std::vector > points = get_QGaussLobatto_points(degree); unsigned int k=0; for (unsigned int iz=0; iz <= ((codim>2) ? this->degree : 0) ; ++iz) for (unsigned int iy=0; iy <= ((codim>1) ? this->degree : 0) ; ++iy) for (unsigned int ix=0; ix<=this->degree; ++ix) { - p(0) = ix * step; + Point p; + + p(0) = points[ix][0]; if (codim>1) - p(1) = iy * step; + p(1) = points[iy][0]; if (codim>2) - p(2) = iz * step; + p(2) = points[iz][0]; this->unit_face_support_points[k++] = p; } AssertDimension (k, this->unit_face_support_points.size()); } + + // initialize unit support points + this->unit_support_points.resize(GeometryInfo::faces_per_cell* + this->unit_face_support_points.size()); + const unsigned int n_face_dofs = this->unit_face_support_points.size(); + for (unsigned int i=0; iunit_support_points[n_face_dofs*2*d+i][e] = + this->unit_face_support_points[i][c]; + this->unit_support_points[n_face_dofs*(2*d+1)+i][e] = + this->unit_face_support_points[i][c]; + this->unit_support_points[n_face_dofs*(2*d+1)+i][d] = 1; + ++c; + } + } } @@ -86,6 +121,168 @@ FE_FaceQ::get_name () const +template +void +FE_FaceQ:: +get_face_interpolation_matrix (const FiniteElement &x_source_fe, + FullMatrix &interpolation_matrix) const +{ + // this function is similar to the respective method in FE_Q + + // this is only implemented, if the source FE is also a FE_FaceQ element + AssertThrow ((dynamic_cast *>(&x_source_fe) != 0), + (typename FiniteElement:: + ExcInterpolationNotImplemented())); + + Assert (interpolation_matrix.n() == this->dofs_per_face, + ExcDimensionMismatch (interpolation_matrix.n(), + this->dofs_per_face)); + Assert (interpolation_matrix.m() == x_source_fe.dofs_per_face, + ExcDimensionMismatch (interpolation_matrix.m(), + x_source_fe.dofs_per_face)); + + // ok, source is a FaceQ element, so we will be able to do the work + const FE_FaceQ &source_fe + = dynamic_cast&>(x_source_fe); + + // Make sure that the element for which the DoFs should be constrained is + // the one with the higher polynomial degree. Actually the procedure will + // work also if this assertion is not satisfied. But the matrices produced + // in that case might lead to problems in the hp procedures, which use this + // method. + Assert (this->dofs_per_face <= source_fe.dofs_per_face, + (typename FiniteElement:: + ExcInterpolationNotImplemented ())); + + // generate a quadrature with the unit face support points. + const Quadrature face_quadrature (source_fe.get_unit_face_support_points ()); + + // Rule of thumb for FP accuracy, that can be expected for a given + // polynomial degree. This value is used to cut off values close to zero. + const double eps = 2e-13*(this->degree+1)*(dim-1); + + // compute the interpolation matrix by simply taking the value at the + // support points. + for (unsigned int i=0; i &p = face_quadrature.point (i); + + for (unsigned int j=0; jdofs_per_face; ++j) + { + double matrix_entry = this->poly_space.compute_value (j, p); + + // Correct the interpolated value. I.e. if it is close to 1 or 0, + // make it exactly 1 or 0. Unfortunately, this is required to avoid + // problems with higher order elements. + if (std::fabs (matrix_entry - 1.0) < eps) + matrix_entry = 1.0; + if (std::fabs (matrix_entry) < eps) + matrix_entry = 0.0; + + interpolation_matrix(i,j) = matrix_entry; + } + } + + // make sure that the row sum of each of the matrices is 1 at this + // point. this must be so since the shape functions sum up to 1 + for (unsigned int j=0; jdofs_per_face; ++i) + sum += interpolation_matrix(j,i); + + Assert (std::fabs(sum-1) < eps, ExcInternalError()); + } +} + + + +template +void +FE_FaceQ:: +get_subface_interpolation_matrix (const FiniteElement &x_source_fe, + const unsigned int subface, + FullMatrix &interpolation_matrix) const +{ + // this function is similar to the respective method in FE_Q + + Assert (interpolation_matrix.n() == this->dofs_per_face, + ExcDimensionMismatch (interpolation_matrix.n(), + this->dofs_per_face)); + Assert (interpolation_matrix.m() == x_source_fe.dofs_per_face, + ExcDimensionMismatch (interpolation_matrix.m(), + x_source_fe.dofs_per_face)); + + // see if source is a FaceQ element + if (const FE_FaceQ *source_fe + = dynamic_cast *>(&x_source_fe)) + { + + // Make sure that the element for which the DoFs should be constrained + // is the one with the higher polynomial degree. Actually the procedure + // will work also if this assertion is not satisfied. But the matrices + // produced in that case might lead to problems in the hp procedures, + // which use this method. + Assert (this->dofs_per_face <= source_fe->dofs_per_face, + (typename FiniteElement:: + ExcInterpolationNotImplemented ())); + + // generate a quadrature with the unit face support points. + const Quadrature face_quadrature (source_fe->get_unit_face_support_points ()); + + // Rule of thumb for FP accuracy, that can be expected for a given + // polynomial degree. This value is used to cut off values close to + // zero. + const double eps = 2e-13*(this->degree+1)*(dim-1); + + // compute the interpolation matrix by simply taking the value at the + // support points. + for (unsigned int i=0; idofs_per_face; ++i) + { + const Point p = + GeometryInfo::child_to_cell_coordinates (face_quadrature.point(i), + subface); + + for (unsigned int j=0; jdofs_per_face; ++j) + { + double matrix_entry = this->poly_space.compute_value (j, p); + + // Correct the interpolated value. I.e. if it is close to 1 or 0, + // make it exactly 1 or 0. Unfortunately, this is required to avoid + // problems with higher order elements. + if (std::fabs (matrix_entry - 1.0) < eps) + matrix_entry = 1.0; + if (std::fabs (matrix_entry) < eps) + matrix_entry = 0.0; + + interpolation_matrix(i,j) = matrix_entry; + } + } + + // make sure that the row sum of each of the matrices is 1 at this + // point. this must be so since the shape functions sum up to 1 + for (unsigned int j=0; jdofs_per_face; ++j) + { + double sum = 0.; + + for (unsigned int i=0; idofs_per_face; ++i) + sum += interpolation_matrix(j,i); + + Assert (std::fabs(sum-1) < eps, ExcInternalError()); + } + } + else if (dynamic_cast *>(&x_source_fe) != 0) + { + // nothing to do here, the FE_Nothing has no degrees of freedom anyway + } + else + AssertThrow (false,(typename FiniteElement:: + ExcInterpolationNotImplemented())); +} + + + template bool FE_FaceQ::has_support_on_face ( @@ -96,6 +293,7 @@ FE_FaceQ::has_support_on_face ( } + template std::vector FE_FaceQ::get_dpo_vector (const unsigned int deg) @@ -109,6 +307,41 @@ FE_FaceQ::get_dpo_vector (const unsigned int deg) +template +bool +FE_FaceQ::hp_constraints_are_implemented () const +{ + return true; +} + + + +template +FiniteElementDomination::Domination +FE_FaceQ:: +compare_for_face_domination (const FiniteElement &fe_other) const +{ + if (const FE_FaceQ *fe_q_other + = dynamic_cast*>(&fe_other)) + { + if (this->degree < fe_q_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_q_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (dynamic_cast*>(&fe_other) != 0) + { + // the FE_Nothing has no degrees of freedom and it is typically used in + // a context where we don't require any continuity along the interface + return FiniteElementDomination::no_requirements; + } + + Assert (false, ExcNotImplemented()); + return FiniteElementDomination::neither_element_dominates; +} + // explicit instantiations #include "fe_face.inst" diff --git a/deal.II/source/fe/fe_q_base.cc b/deal.II/source/fe/fe_q_base.cc index 77aab44e1a..a43e3be528 100644 --- a/deal.II/source/fe/fe_q_base.cc +++ b/deal.II/source/fe/fe_q_base.cc @@ -606,8 +606,7 @@ get_face_interpolation_matrix (const FiniteElement &x_source_fe, for (unsigned int i=0; idofs_per_face; ++i) sum += interpolation_matrix(j,i); - Assert (std::fabs(sum-1) < 2e-13*this->degree*(dim-1), - ExcInternalError()); + Assert (std::fabs(sum-1) < eps, ExcInternalError()); } } @@ -688,8 +687,7 @@ get_subface_interpolation_matrix (const FiniteElement &x_source_fe for (unsigned int i=0; idofs_per_face; ++i) sum += interpolation_matrix(j,i); - Assert (std::fabs(sum-1) < 2e-13*this->degree*dim, - ExcInternalError()); + Assert (std::fabs(sum-1) < eps, ExcInternalError()); } } else if (dynamic_cast *>(&x_source_fe) != 0) @@ -754,7 +752,7 @@ hp_line_dof_identities (const FiniteElement &fe_other) const { // dofs are located along lines, so two dofs are identical if they are // located at identical positions. if we had only equidistant points, we - // could simple check for similarity like (i+1)*q == (j+1)*p, but we + // could simply check for similarity like (i+1)*q == (j+1)*p, but we // might have other support points (e.g. Gauss-Lobatto // points). Therefore, read the points in unit_support_points for the // first coordinate direction. We take the lexicographic ordering of the @@ -988,11 +986,132 @@ FE_Q_Base::initialize_quad_dof_index_permutation () +template +unsigned int +FE_Q_Base:: +face_to_cell_index (const unsigned int face_index, + const unsigned int face, + const bool face_orientation, + const bool face_flip, + const bool face_rotation) const +{ + Assert (face_index < this->dofs_per_face, + ExcIndexRange(face_index, 0, this->dofs_per_face)); + Assert (face < GeometryInfo::faces_per_cell, + ExcIndexRange(face, 0, GeometryInfo::faces_per_cell)); + +//TODO: we could presumably solve the 3d case below using the +// adjust_quad_dof_index_for_face_orientation_table field. for the +// 2d case, we can't use adjust_line_dof_index_for_line_orientation_table +// since that array is empty (presumably because we thought that +// there are no flipped edges in 2d, but these can happen in +// DoFTools::make_periodicity_constraints, for example). so we +// would need to either fill this field, or rely on derived classes +// implementing this function, as we currently do + + // we need to distinguish between DoFs on vertices, lines and in 3d quads. + // do so in a sequence of if-else statements + if (face_index < this->first_face_line_index) + // DoF is on a vertex + { + // get the number of the vertex on the face that corresponds to this DoF, + // along with the number of the DoF on this vertex + const unsigned int face_vertex = face_index / this->dofs_per_vertex; + const unsigned int dof_index_on_vertex = face_index % this->dofs_per_vertex; + + // then get the number of this vertex on the cell and translate + // this to a DoF number on the cell + return (GeometryInfo::face_to_cell_vertices(face, face_vertex, + face_orientation, + face_flip, + face_rotation) + * this->dofs_per_vertex + + + dof_index_on_vertex); + } + else if (face_index < this->first_face_quad_index) + // DoF is on a face + { + // do the same kind of translation as before. we need to only consider + // DoFs on the lines, i.e., ignoring those on the vertices + const unsigned int index = face_index - this->first_face_line_index; + + const unsigned int face_line = index / this->dofs_per_line; + const unsigned int dof_index_on_line = index % this->dofs_per_line; + + // we now also need to adjust the line index for the case of + // face orientation, face flips, etc + unsigned int adjusted_dof_index_on_line; + switch (dim) + { + case 1: + Assert (false, ExcInternalError()); + + case 2: + // in 2d, only face_flip has a meaning. if it is set, consider + // dofs in reverse order + if (face_flip == false) + adjusted_dof_index_on_line = dof_index_on_line; + else + adjusted_dof_index_on_line = this->dofs_per_line - dof_index_on_line - 1; + break; + + case 3: + // in 3d, things are difficult. someone will have to think + // about how this code here should look like, by drawing a bunch + // of pictures of how all the faces can look like with the various + // flips and rotations. + // + // that said, the Q2 case is easy enough to implement, as is the case + // where everything is in standard orientation + Assert ((this->dofs_per_line <= 1) || + ((face_orientation == true) && + (face_flip == false) && + (face_rotation == false)), + ExcNotImplemented()); + adjusted_dof_index_on_line = dof_index_on_line; + break; + } + + return (this->first_line_index + + GeometryInfo::face_to_cell_lines(face, face_line, + face_orientation, + face_flip, + face_rotation) + * this->dofs_per_line + + + adjusted_dof_index_on_line); + } + else + // DoF is on a quad + { + Assert (dim >= 3, ExcInternalError()); + + // ignore vertex and line dofs + const unsigned int index = face_index - this->first_face_quad_index; + + // the same is true here as above for the 3d case -- someone will + // just have to draw a bunch of pictures. in the meantime, + // we can implement the Q2 case in which it is simple + Assert ((this->dofs_per_quad <= 1) || + ((face_orientation == true) && + (face_flip == false) && + (face_rotation == false)), + ExcNotImplemented()); + return (this->first_quad_index + + face * this->dofs_per_quad + + index); + } +} + + + template std::vector FE_Q_Base::get_dpo_vector(const unsigned int deg) { + AssertThrow(deg>0,ExcMessage("FE_Q needs to be of degree > 0.")); std::vector dpo(dim+1, 1U); for (unsigned int i=1; i -FESystem::InternalData::InternalData(const unsigned int n_base_elements): +FESystem::InternalData::InternalData(const unsigned int n_base_elements, + const bool compute_hessians) +: + compute_hessians (compute_hessians), base_fe_datas(n_base_elements), base_fe_values_datas(n_base_elements) {} @@ -745,6 +748,45 @@ FESystem } +template +unsigned int +FESystem:: +face_to_cell_index (const unsigned int face_dof_index, + const unsigned int face, + const bool face_orientation, + const bool face_flip, + const bool face_rotation) const +{ + // we need to ask the base elements how they want to translate + // the DoFs within their own numbering. thus, translate to + // the base element numbering and then back + const std::pair, unsigned int> + face_base_index = this->face_system_to_base_index(face_dof_index); + + const unsigned int + base_face_to_cell_index + = this->base_element(face_base_index.first.first).face_to_cell_index (face_base_index.second, + face, + face_orientation, + face_flip, + face_rotation); + + // it would be nice if we had a base_to_system_index function, but + // all that exists is a component_to_system_index function. we can't do + // this here because it won't work for non-primitive elements. consequently, + // simply do a loop over all dofs till we find whether it corresponds + // to the one we're interested in -- crude, maybe, but works for now + const std::pair, unsigned int> + target = std::make_pair (face_base_index.first, base_face_to_cell_index); + for (unsigned int i=0; idofs_per_cell; ++i) + if (this->system_to_base_index(i) == target) + return i; + + Assert (false, ExcInternalError()); + return numbers::invalid_unsigned_int; +} + + //--------------------------------------------------------------------------- // Data field initialization @@ -800,7 +842,8 @@ FESystem::get_data (const UpdateFlags flags_, const Quadrature &quadrature) const { UpdateFlags flags = flags_; - InternalData *data = new InternalData(this->n_base_elements()); + InternalData *data = new InternalData(this->n_base_elements(), + flags & update_hessians); data->update_once = update_once (flags); data->update_each = update_each (flags); @@ -811,7 +854,6 @@ FESystem::get_data (const UpdateFlags flags_, // finite differencing are required, // then initialize some objects for // that - data->compute_hessians = flags & update_hessians; if (data->compute_hessians) { // delete @@ -887,14 +929,14 @@ FESystem::get_face_data ( const Quadrature &quadrature) const { UpdateFlags flags = flags_; - InternalData *data = new InternalData(this->n_base_elements()); + InternalData *data = new InternalData(this->n_base_elements(), + flags & update_hessians); data->update_once = update_once (flags); data->update_each = update_each (flags); flags = data->update_once | data->update_each; UpdateFlags sub_flags = flags; - data->compute_hessians = flags & update_hessians; if (data->compute_hessians) { sub_flags = UpdateFlags (sub_flags ^ update_hessians); @@ -939,14 +981,14 @@ FESystem::get_subface_data ( const Quadrature &quadrature) const { UpdateFlags flags = flags_; - InternalData *data = new InternalData(this->n_base_elements()); + InternalData *data = new InternalData(this->n_base_elements(), + flags & update_hessians); data->update_once = update_once (flags); data->update_each = update_each (flags); flags = data->update_once | data->update_each; UpdateFlags sub_flags = flags; - data->compute_hessians = flags & update_hessians; if (data->compute_hessians) { sub_flags = UpdateFlags (sub_flags ^ update_hessians); diff --git a/deal.II/source/fe/fe_values.cc b/deal.II/source/fe/fe_values.cc index 0602d5fd09..a94336f669 100644 --- a/deal.II/source/fe/fe_values.cc +++ b/deal.II/source/fe/fe_values.cc @@ -1641,12 +1641,10 @@ namespace internal scalars.resize (n_scalars); for (unsigned int component=0; component::~Scalar (); -#else + // Use a typedef here to work around an issue with gcc-4.1: typedef dealii::FEValuesViews::Scalar ScalarView; scalars[component].ScalarView::~ScalarView (); -#endif + new (&scalars[component]) dealii::FEValuesViews::Scalar(fe_values, component); @@ -1665,12 +1663,10 @@ namespace internal vectors.resize (n_vectors); for (unsigned int component=0; component::~Vector (); -#else + // Use a typedef here to work around an issue with gcc-4.1: typedef dealii::FEValuesViews::Vector VectorView; vectors[component].VectorView::~VectorView (); -#endif + new (&vectors[component]) dealii::FEValuesViews::Vector(fe_values, component); @@ -1685,13 +1681,10 @@ namespace internal symmetric_second_order_tensors.resize(n_symmetric_second_order_tensors); for (unsigned int component = 0; component < n_symmetric_second_order_tensors; ++component) { -#ifndef DEAL_II_EXPLICIT_DESTRUCTOR_BUG - symmetric_second_order_tensors[component] - .dealii::FEValuesViews::SymmetricTensor<2, dim, spacedim>::~SymmetricTensor(); -#else + // Use a typedef here to work around an issue with gcc-4.1: typedef dealii::FEValuesViews::SymmetricTensor<2, dim, spacedim> SymmetricTensorView; symmetric_second_order_tensors[component].SymmetricTensorView::~SymmetricTensorView(); -#endif + new (&symmetric_second_order_tensors[component]) dealii::FEValuesViews::SymmetricTensor<2, dim, spacedim > (fe_values, component); @@ -1707,13 +1700,10 @@ namespace internal second_order_tensors.resize(n_second_order_tensors); for (unsigned int component = 0; component < n_second_order_tensors; ++component) { -#ifndef DEAL_II_EXPLICIT_DESTRUCTOR_BUG - second_order_tensors[component] - .dealii::FEValuesViews::Tensor<2, dim, spacedim>::~Tensor(); -#else + // Use a typedef here to work around an issue with gcc-4.1: typedef dealii::FEValuesViews::Tensor<2, dim, spacedim> TensorView; second_order_tensors[component].TensorView::~TensorView(); -#endif + new (&second_order_tensors[component]) dealii::FEValuesViews::Tensor<2, dim, spacedim > (fe_values, component); diff --git a/deal.II/source/fe/mapping_q.cc b/deal.II/source/fe/mapping_q.cc index 663d77482e..18cb2b1110 100644 --- a/deal.II/source/fe/mapping_q.cc +++ b/deal.II/source/fe/mapping_q.cc @@ -696,7 +696,7 @@ MappingQ::set_laplace_on_quad_vector(Table<2,double> &loqvs) const // one. check this for (unsigned int unit_point=0; unit_pointdegree*this->degree, ExcInternalError()); } diff --git a/deal.II/source/fe/mapping_q_eulerian.cc b/deal.II/source/fe/mapping_q_eulerian.cc index 4e005c2f8f..c8ba737474 100644 --- a/deal.II/source/fe/mapping_q_eulerian.cc +++ b/deal.II/source/fe/mapping_q_eulerian.cc @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include #include #include #include diff --git a/deal.II/source/fe/mapping_q_eulerian.inst.in b/deal.II/source/fe/mapping_q_eulerian.inst.in index dd64c5497f..439ef92f51 100644 --- a/deal.II/source/fe/mapping_q_eulerian.inst.in +++ b/deal.II/source/fe/mapping_q_eulerian.inst.in @@ -25,6 +25,17 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS template class MappingQEulerian; # endif +# ifdef DEAL_II_WITH_TRILINOS + template class MappingQEulerian; + template class MappingQEulerian; + template class MappingQEulerian; + template class MappingQEulerian; +# endif + #endif } diff --git a/deal.II/source/grid/grid_generator.cc b/deal.II/source/grid/grid_generator.cc index e834ca6334..298de0aac3 100644 --- a/deal.II/source/grid/grid_generator.cc +++ b/deal.II/source/grid/grid_generator.cc @@ -46,3784 +46,3794 @@ DEAL_II_NAMESPACE_OPEN -namespace +namespace GridGenerator { - // Corner points of the cube [-1,1]^3 - const Point<3> hexahedron[8] = + namespace { - Point<3>(-1,-1,-1), - Point<3>(+1,-1,-1), - Point<3>(-1,+1,-1), - Point<3>(+1,+1,-1), - Point<3>(-1,-1,+1), - Point<3>(+1,-1,+1), - Point<3>(-1,+1,+1), - Point<3>(+1,+1,+1) - }; - - // Octahedron inscribed in the cube - // [-1,1]^3 - const Point<3> octahedron[6] = - { - Point<3>(-1, 0, 0), - Point<3>( 1, 0, 0), - Point<3>( 0,-1, 0), - Point<3>( 0, 1, 0), - Point<3>( 0, 0,-1), - Point<3>( 0, 0, 1) - }; -} - + // Corner points of the cube [-1,1]^3 + const Point<3> hexahedron[8] = + { + Point<3>(-1,-1,-1), + Point<3>(+1,-1,-1), + Point<3>(-1,+1,-1), + Point<3>(+1,+1,-1), + Point<3>(-1,-1,+1), + Point<3>(+1,-1,+1), + Point<3>(-1,+1,+1), + Point<3>(+1,+1,+1) + }; -template -void -GridGenerator::hyper_rectangle (Triangulation &tria, - const Point &p_1, - const Point &p_2, - const bool colorize) -{ - // First, normalize input such that - // p1 is lower in all coordinate directions. - Point p1(p_1); - Point p2(p_2); + // Octahedron inscribed in the cube + // [-1,1]^3 + const Point<3> octahedron[6] = + { + Point<3>(-1, 0, 0), + Point<3>( 1, 0, 0), + Point<3>( 0,-1, 0), + Point<3>( 0, 1, 0), + Point<3>( 0, 0,-1), + Point<3>( 0, 0, 1) + }; - for (unsigned int i=0; i p2(i)) - std::swap (p1(i), p2(i)); - std::vector > vertices (GeometryInfo::vertices_per_cell); - switch (dim) + /** + * Perform the action specified by the @p colorize flag of the + * hyper_rectangle() function of this class. + */ + template + void + colorize_hyper_rectangle (Triangulation &tria) { - case 1: - vertices[0] = p1; - vertices[1] = p2; - break; - case 2: - vertices[0] = vertices[1] = p1; - vertices[2] = vertices[3] = p2; - - vertices[1](0) = p2(0); - vertices[2](0) = p1(0); - break; - case 3: - vertices[0] = vertices[1] = vertices[2] = vertices[3] = p1; - vertices[4] = vertices[5] = vertices[6] = vertices[7] = p2; + // there is nothing to do in 1d + if (dim > 1) + { + // there is only one cell, so + // simple task + const typename Triangulation::cell_iterator + cell = tria.begin(); + for (unsigned int f=0; f::faces_per_cell; ++f) + cell->face(f)->set_boundary_indicator (f); + } + } - vertices[1](0) = p2(0); - vertices[2](1) = p2(1); - vertices[3](0) = p2(0); - vertices[3](1) = p2(1); - vertices[4](0) = p1(0); - vertices[4](1) = p1(1); - vertices[5](1) = p1(1); - vertices[6](0) = p1(0); - break; - default: - Assert (false, ExcNotImplemented ()); + void + colorize_subdivided_hyper_rectangle (Triangulation<1> &tria, + const Point<1> &, + const Point<1> &, + const double) + { + for (Triangulation<1>::cell_iterator cell = tria.begin(); + cell != tria.end(); ++cell) + if (cell->center()(0) > 0) + cell->set_material_id(1); + // boundary indicators are set to + // 0 (left) and 1 (right) by default. } - // Prepare cell data - std::vector > cells (1); - for (unsigned int i=0; i::vertices_per_cell; ++i) - cells[0].vertices[i] = i; - cells[0].material_id = 0; - tria.create_triangulation (vertices, cells, SubCellData()); - // Assign boundary indicators - if (colorize) - colorize_hyper_rectangle (tria); -} + template + void + colorize_subdivided_hyper_rectangle (Triangulation &tria, + const Point &p1, + const Point &p2, + const double epsilon) + { + // run through all faces and check + // if one of their center coordinates matches + // one of the corner points. Comparisons + // are made using an epsilon which + // should be smaller than the smallest cell + // diameter. + typename Triangulation::face_iterator face = tria.begin_face(), + endface = tria.end_face(); + for (; face!=endface; ++face) + { + if (face->boundary_indicator() == 0) + { + const Point center (face->center()); + if (std::abs(center(0)-p1[0]) < epsilon) + face->set_boundary_indicator(0); + else if (std::abs(center(0) - p2[0]) < epsilon) + face->set_boundary_indicator(1); + else if (dim > 1 && std::abs(center(1) - p1[1]) < epsilon) + face->set_boundary_indicator(2); + else if (dim > 1 && std::abs(center(1) - p2[1]) < epsilon) + face->set_boundary_indicator(3); + else if (dim > 2 && std::abs(center(2) - p1[2]) < epsilon) + face->set_boundary_indicator(4); + else if (dim > 2 && std::abs(center(2) - p2[2]) < epsilon) + face->set_boundary_indicator(5); + else + // triangulation says it + // is on the boundary, + // but we could not find + // on which boundary. + Assert (false, ExcInternalError()); -template -void -GridGenerator::colorize_hyper_rectangle (Triangulation &tria) -{ - // there is nothing to do in 1d - if (dim > 1) - { - // there is only one cell, so - // simple task - const typename Triangulation::cell_iterator - cell = tria.begin(); - for (unsigned int f=0; f::faces_per_cell; ++f) - cell->face(f)->set_boundary_indicator (f); + } + } + for (typename Triangulation::cell_iterator cell = tria.begin(); + cell != tria.end(); ++cell) + { + char id = 0; + for (unsigned int d=0; dcenter()(d) > 0) id += 1 << d; + cell->set_material_id(id); + } } -} - -template -void GridGenerator::hyper_cube (Triangulation &tria, - const double left, - const double right) -{ - Assert (left < right, - ExcMessage ("Invalid left-to-right bounds of hypercube")); - - Point p1; - Point p2; + /** + * Assign boundary number zero to the inner shell boundary and 1 to the + * outer. + */ + void colorize_hyper_shell (Triangulation<1> &, + const Point<1> &, + const double, + const double) + { + Assert (false, ExcNotImplemented()); + } - p1(spacedim-1) = 0; - p2(spacedim-1) = 0; - for (unsigned int i=0; i &tria, + const Point<2> &, + const double, + const double) { - p1(i) = left; - p2(i) = right; + // In spite of receiving geometrical + // data, we do this only based on + // topology. + + // For the mesh based on cube, + // this is highly irregular + for (Triangulation<2>::cell_iterator cell = tria.begin (); + cell != tria.end (); ++cell) + { + Assert(cell->face(2)->at_boundary(), ExcInternalError()); + cell->face (2)->set_boundary_indicator (1); + } } - hyper_rectangle (tria, p1, p2); -} + /** + * Assign boundary number zero to the inner shell boundary and 1 to the + * outer. + */ + void + colorize_hyper_shell (Triangulation<3> &tria, + const Point<3> &, + const double, + const double) + { + // the following uses a good amount + // of knowledge about the + // orientation of cells. this is + // probably not good style... + if (tria.n_cells() == 6) + { + Triangulation<3>::cell_iterator cell = tria.begin(); -void -GridGenerator::moebius ( - Triangulation<3> &tria, - const size_type n_cells, - const unsigned int n_rotations, - const double R, - const double r) -{ - const unsigned int dim=3; - Assert (n_cells>4, ExcMessage("More than 4 cells are needed to create a moebius grid.")); - Assert (r>0 && R>0, ExcMessage("Outer and inner radius must be positive.")); - Assert (R>r, ExcMessage("Outer radius must be greater than inner radius.")); + cell->face(4)->set_boundary_indicator(1); + Assert (cell->face(4)->at_boundary(), ExcInternalError()); + (++cell)->face(2)->set_boundary_indicator(1); + Assert (cell->face(2)->at_boundary(), ExcInternalError()); - std::vector > vertices (4*n_cells); - double beta_step=n_rotations*numbers::PI/2.0/n_cells; - double alpha_step=2.0*numbers::PI/n_cells; + (++cell)->face(2)->set_boundary_indicator(1); + Assert (cell->face(2)->at_boundary(), ExcInternalError()); - for (size_type i=0; iface(0)->set_boundary_indicator(1); + Assert (cell->face(0)->at_boundary(), ExcInternalError()); - size_type offset=0; + (++cell)->face(2)->set_boundary_indicator(1); + Assert (cell->face(2)->at_boundary(), ExcInternalError()); - std::vector > cells (n_cells); - for (size_type i=0; iface(0)->set_boundary_indicator(1); + Assert (cell->face(0)->at_boundary(), ExcInternalError()); + } + else if (tria.n_cells() == 12) { - cells[i].vertices[0+4*j]=offset+0+4*j; - cells[i].vertices[1+4*j]=offset+3+4*j; - cells[i].vertices[2+4*j]=offset+2+4*j; - cells[i].vertices[3+4*j]=offset+1+4*j; + // again use some internal + // knowledge + for (Triangulation<3>::cell_iterator cell = tria.begin(); + cell != tria.end(); ++cell) + { + Assert (cell->face(5)->at_boundary(), ExcInternalError()); + cell->face(5)->set_boundary_indicator(1); + } + } + else if (tria.n_cells() == 96) + { + // the 96-cell hypershell is + // based on a once refined + // 12-cell mesh. consequently, + // since the outer faces all + // are face_no==5 above, so + // they are here (unless they + // are in the interior). Use + // this to assign boundary + // indicators, but also make + // sure that we encounter + // exactly 48 such faces + unsigned int count = 0; + for (Triangulation<3>::cell_iterator cell = tria.begin(); + cell != tria.end(); ++cell) + if (cell->face(5)->at_boundary()) + { + cell->face(5)->set_boundary_indicator(1); + ++count; + } + Assert (count == 48, ExcInternalError()); } - offset+=4; - cells[i].material_id=0; + else + Assert (false, ExcNotImplemented()); } - // now correct the last four vertices - cells[n_cells-1].vertices[4]=(0+n_rotations)%4; - cells[n_cells-1].vertices[5]=(3+n_rotations)%4; - cells[n_cells-1].vertices[6]=(2+n_rotations)%4; - cells[n_cells-1].vertices[7]=(1+n_rotations)%4; - GridReordering::invert_all_cells_of_negative_grid(vertices,cells); - tria.create_triangulation_compatibility (vertices, cells, SubCellData()); -} + /** + * Assign boundary number zero the inner shell boundary, one to the outer + * shell boundary, two to the face with x=0, three to the face with y=0, + * four to the face with z=0. + */ + void + colorize_quarter_hyper_shell(Triangulation<3> &tria, + const Point<3> ¢er, + const double inner_radius, + const double outer_radius) + { + if (tria.n_cells() != 3) + AssertThrow (false, ExcNotImplemented()); + double middle = (outer_radius-inner_radius)/2e0 + inner_radius; + double eps = 1e-3*middle; + Triangulation<3>::cell_iterator cell = tria.begin(); -void -GridGenerator::torus (Triangulation<2,3> &tria, - const double R, - const double r) -{ - Assert (R>r, ExcMessage("Outer radius must be greater than inner radius.")); - - const unsigned int dim=2; - const unsigned int spacedim=3; - std::vector > vertices (16); - - vertices[0]=Point(R-r,0,0); - vertices[1]=Point(R,-r,0); - vertices[2]=Point(R+r,0,0); - vertices[3]=Point(R, r,0); - vertices[4]=Point(0,0,R-r); - vertices[5]=Point(0,-r,R); - vertices[6]=Point(0,0,R+r); - vertices[7]=Point(0,r,R); - vertices[8]=Point(-(R-r),0,0); - vertices[9]=Point(-R,-r,0); - vertices[10]=Point(-(R+r),0,0); - vertices[11]=Point(-R, r,0); - vertices[12]=Point(0,0,-(R-r)); - vertices[13]=Point(0,-r,-R); - vertices[14]=Point(0,0,-(R+r)); - vertices[15]=Point(0,r,-R); - - std::vector > cells (16); - //Right Hand Orientation - cells[0].vertices[0] = 0; - cells[0].vertices[1] = 4; - cells[0].vertices[2] = 7; - cells[0].vertices[3] = 3; - cells[0].material_id = 0; - - cells[1].vertices[0] = 1; - cells[1].vertices[1] = 5; - cells[1].vertices[2] = 4; - cells[1].vertices[3] = 0; - cells[1].material_id = 0; - - cells[2].vertices[0] = 2; - cells[2].vertices[1] = 6; - cells[2].vertices[2] = 5; - cells[2].vertices[3] = 1; - cells[2].material_id = 0; - - cells[3].vertices[0] = 3; - cells[3].vertices[1] = 7; - cells[3].vertices[2] = 6; - cells[3].vertices[3] = 2; - cells[3].material_id = 0; - - cells[4].vertices[0] = 4; - cells[4].vertices[1] = 8; - cells[4].vertices[2] = 11; - cells[4].vertices[3] = 7; - cells[4].material_id = 0; - - cells[5].vertices[0] = 5; - cells[5].vertices[1] = 9; - cells[5].vertices[2] = 8; - cells[5].vertices[3] = 4; - cells[5].material_id = 0; - - cells[6].vertices[0] = 6; - cells[6].vertices[1] = 10; - cells[6].vertices[2] = 9; - cells[6].vertices[3] = 5; - cells[6].material_id = 0; - - cells[7].vertices[0] = 7; - cells[7].vertices[1] = 11; - cells[7].vertices[2] = 10; - cells[7].vertices[3] = 6; - cells[7].material_id = 0; - - cells[8].vertices[0] = 8; - cells[8].vertices[1] = 12; - cells[8].vertices[2] = 15; - cells[8].vertices[3] = 11; - cells[8].material_id = 0; - - cells[9].vertices[0] = 9; - cells[9].vertices[1] = 13; - cells[9].vertices[2] = 12; - cells[9].vertices[3] = 8; - cells[9].material_id = 0; - - cells[10].vertices[0] = 10; - cells[10].vertices[1] = 14; - cells[10].vertices[2] = 13; - cells[10].vertices[3] = 9; - cells[10].material_id = 0; - - cells[11].vertices[0] = 11; - cells[11].vertices[1] = 15; - cells[11].vertices[2] = 14; - cells[11].vertices[3] = 10; - cells[11].material_id = 0; - - cells[12].vertices[0] = 12; - cells[12].vertices[1] = 0; - cells[12].vertices[2] = 3; - cells[12].vertices[3] = 15; - cells[12].material_id = 0; - - cells[13].vertices[0] = 13; - cells[13].vertices[1] = 1; - cells[13].vertices[2] = 0; - cells[13].vertices[3] = 12; - cells[13].material_id = 0; - - cells[14].vertices[0] = 14; - cells[14].vertices[1] = 2; - cells[14].vertices[2] = 1; - cells[14].vertices[3] = 13; - cells[14].material_id = 0; - - cells[15].vertices[0] = 15; - cells[15].vertices[1] = 3; - cells[15].vertices[2] = 2; - cells[15].vertices[3] = 14; - cells[15].material_id = 0; - - // Must call this to be able to create a - // correct triangulation in dealii, read - // GridReordering<> doc - GridReordering::reorder_cells (cells); - tria.create_triangulation_compatibility (vertices, cells, SubCellData()); -} + for (; cell!=tria.end(); ++cell) + for (unsigned int f=0; f::faces_per_cell; ++f) + { + if (!cell->face(f)->at_boundary()) + continue; + double radius = cell->face(f)->center().norm() - center.norm(); + if (std::fabs(cell->face(f)->center()(0)) < eps ) // x = 0 set boundary 2 + { + cell->face(f)->set_boundary_indicator(2); + for (unsigned int j=0; j::lines_per_face; ++j) + if (cell->face(f)->line(j)->at_boundary()) + if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) > eps) + cell->face(f)->line(j)->set_boundary_indicator(2); + } + else if (std::fabs(cell->face(f)->center()(1)) < eps) // y = 0 set boundary 3 + { + cell->face(f)->set_boundary_indicator(3); + for (unsigned int j=0; j::lines_per_face; ++j) + if (cell->face(f)->line(j)->at_boundary()) + if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) > eps) + cell->face(f)->line(j)->set_boundary_indicator(3); + } + else if (std::fabs(cell->face(f)->center()(2)) < eps ) // z = 0 set boundary 4 + { + cell->face(f)->set_boundary_indicator(4); + for (unsigned int j=0; j::lines_per_face; ++j) + if (cell->face(f)->line(j)->at_boundary()) + if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) > eps) + cell->face(f)->line(j)->set_boundary_indicator(4); + } + else if (radius < middle) // inner radius set boundary 0 + { + cell->face(f)->set_boundary_indicator(0); + for (unsigned int j=0; j::lines_per_face; ++j) + if (cell->face(f)->line(j)->at_boundary()) + if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) < eps) + cell->face(f)->line(j)->set_boundary_indicator(0); + } + else if (radius > middle) // outer radius set boundary 1 + { + cell->face(f)->set_boundary_indicator(1); + for (unsigned int j=0; j::lines_per_face; ++j) + if (cell->face(f)->line(j)->at_boundary()) + if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) < eps) + cell->face(f)->line(j)->set_boundary_indicator(1); + } + else + AssertThrow (false, ExcInternalError()); + } + } -// Implementation for 2D only -template<> -void -GridGenerator::parallelogram (Triangulation<2> &tria, - const Point<2> (&corners)[2], - const bool colorize) -{ - std::vector > vertices (GeometryInfo<2>::vertices_per_cell); - - vertices[1] = corners[0]; - vertices[2] = corners[1]; - vertices[3] = vertices[1] + vertices[2]; - // Prepare cell data - std::vector > cells (1); - for (unsigned int i=0; i::vertices_per_cell; ++i) - cells[0].vertices[i] = i; - cells[0].material_id = 0; - - tria.create_triangulation (vertices, cells, SubCellData()); - - // Assign boundary indicators - if (colorize) - colorize_hyper_rectangle (tria); -} + } -template<> -void -GridGenerator::parallelogram (Triangulation<2> &tria, - const Tensor<2,2> &corners, - const bool colorize) -{ - // simply pass everything to the other function of same name - const Point<2> x[2] = { corners[0], corners[1] }; - parallelogram (tria, x, colorize); -} + template + void + hyper_rectangle (Triangulation &tria, + const Point &p_1, + const Point &p_2, + const bool colorize) + { + // First, normalize input such that + // p1 is lower in all coordinate directions. + Point p1(p_1); + Point p2(p_2); + for (unsigned int i=0; i p2(i)) + std::swap (p1(i), p2(i)); + std::vector > vertices (GeometryInfo::vertices_per_cell); + switch (dim) + { + case 1: + vertices[0] = p1; + vertices[1] = p2; + break; + case 2: + vertices[0] = vertices[1] = p1; + vertices[2] = vertices[3] = p2; + + vertices[1](0) = p2(0); + vertices[2](0) = p1(0); + break; + case 3: + vertices[0] = vertices[1] = vertices[2] = vertices[3] = p1; + vertices[4] = vertices[5] = vertices[6] = vertices[7] = p2; + + vertices[1](0) = p2(0); + vertices[2](1) = p2(1); + vertices[3](0) = p2(0); + vertices[3](1) = p2(1); + + vertices[4](0) = p1(0); + vertices[4](1) = p1(1); + vertices[5](1) = p1(1); + vertices[6](0) = p1(0); + + break; + default: + Assert (false, ExcNotImplemented ()); + } -// Parallelepiped implementation in 1d, 2d, and 3d. @note The -// implementation in 1d is similar to hyper_rectangle(), and in 2d is -// similar to parallelogram(). -// -// The GridReordering::reorder_grid is made use of towards the end of -// this function. Thus the triangulation is explicitly constructed for -// all dim here since it is slightly different in that respect -// (cf. hyper_rectangle(), parallelogram()). -template -void -GridGenerator::parallelepiped (Triangulation &tria, - const Point (&corners) [dim], - const bool colorize) -{ - // Check that none of the user defined vertices overlap - for (unsigned int i=0; i > cells (1); + for (unsigned int i=0; i::vertices_per_cell; ++i) + cells[0].vertices[i] = i; + cells[0].material_id = 0; - // Note: vertex[0] is the origin and is initialised as so here: - std::vector > vertices (GeometryInfo::vertices_per_cell); + tria.create_triangulation (vertices, cells, SubCellData()); - switch (dim) - { - // A line (1d parallelepiped) - case 1: - vertices[1] = corners[0]; - break; + // Assign boundary indicators + if (colorize) + colorize_hyper_rectangle (tria); + } - // A parallelogram (2d parallelepiped) - case 2: - // assign corners to vertices: - vertices[1] = corners[0]; - vertices[2] = corners[1]; - // compose the remaining vertex: - vertices[3] = vertices[1] + vertices[2]; - break; + template + void hyper_cube (Triangulation &tria, + const double left, + const double right) + { + Assert (left < right, + ExcMessage ("Invalid left-to-right bounds of hypercube")); - // A parallelepiped (3d parallelepiped) - case 3: - // assign corners to vertices: - vertices[1] = corners[0]; - vertices[2] = corners[1]; - vertices[4] = corners[2]; - - // compose the remaining vertices: - vertices[3] = vertices[1] + vertices[2]; - vertices[5] = vertices[1] + vertices[4]; - vertices[6] = vertices[2] + vertices[4]; - vertices[7] = vertices[1] + vertices[2] + vertices[4]; - break; + Point p1; + Point p2; - default: - Assert (false, ExcNotImplemented()); - } + p1(spacedim-1) = 0; + p2(spacedim-1) = 0; - // Prepare cell data and wipe material identity - std::vector > cells (1); - for (unsigned int i=0; i::vertices_per_cell; ++i) - cells[0].vertices[i] = i; - cells[0].material_id = 0; + for (unsigned int i=0; i::reorder_cells (cells); - tria.create_triangulation (vertices, cells, SubCellData()); - // Finally assign boundary indicators according to hyper_rectangle - if (colorize) - colorize_hyper_rectangle (tria); -} -template -void -GridGenerator::subdivided_parallelepiped (Triangulation &tria, - const size_type n_subdivisions, - const Point (&corners) [dim], - const bool colorize) -{ - // Equalise number of subdivisions in each dim-direction, heir - // validity will be checked later - size_type (n_subdivisions_) [dim]; - for (unsigned int i=0; i &tria, + const unsigned int n_cells, + const unsigned int n_rotations, + const double R, + const double r) + { + const unsigned int dim=3; + Assert (n_cells>4, ExcMessage("More than 4 cells are needed to create a moebius grid.")); + Assert (r>0 && R>0, ExcMessage("Outer and inner radius must be positive.")); + Assert (R>r, ExcMessage("Outer radius must be greater than inner radius.")); -template -void -GridGenerator::subdivided_parallelepiped (Triangulation &tria, - const size_type ( n_subdivisions) [dim], - const Point (&corners) [dim], - const bool colorize) -{ - // Zero n_subdivisions is the origin only, which makes no sense - for (unsigned int i=0; i0, ExcInvalidRepetitions(n_subdivisions[i])); - // Check corners do not overlap (unique) - for (unsigned int i=0; i > vertices (4*n_cells); + double beta_step=n_rotations*numbers::PI/2.0/n_cells; + double alpha_step=2.0*numbers::PI/n_cells; - // Create a list of points - Point (delta) [dim]; + for (unsigned int i=0; i > points; + unsigned int offset=0; - switch (dim) - { - case 1: - for (size_type x=0; x<=n_subdivisions[0]; ++x) - points.push_back (Point (x*delta[0])); - break; + std::vector > cells (n_cells); + for (unsigned int i=0; i (x*delta[0] + y*delta[1])); - break; + // now correct the last four vertices + cells[n_cells-1].vertices[4]=(0+n_rotations)%4; + cells[n_cells-1].vertices[5]=(3+n_rotations)%4; + cells[n_cells-1].vertices[6]=(2+n_rotations)%4; + cells[n_cells-1].vertices[7]=(1+n_rotations)%4; - case 3: - for (size_type z=0; z<=n_subdivisions[2]; ++z) - for (size_type y=0; y<=n_subdivisions[1]; ++y) - for (size_type x=0; x<=n_subdivisions[0]; ++x) - points.push_back (Point (x*delta[0] + y*delta[1] + z*delta[2])); - break; + GridReordering::invert_all_cells_of_negative_grid(vertices,cells); + tria.create_triangulation_compatibility (vertices, cells, SubCellData()); + } - default: - Assert (false, ExcNotImplemented()); - } - // Prepare cell data - size_type n_cells = 1; - for (unsigned int i=0; i > cells (n_cells); - // Create fixed ordering of - switch (dim) - { - case 1: - for (size_type x=0; x &tria, + const double R, + const double r) + { + Assert (R>r, ExcMessage("Outer radius must be greater than inner radius.")); + + const unsigned int dim=2; + const unsigned int spacedim=3; + std::vector > vertices (16); + + vertices[0]=Point(R-r,0,0); + vertices[1]=Point(R,-r,0); + vertices[2]=Point(R+r,0,0); + vertices[3]=Point(R, r,0); + vertices[4]=Point(0,0,R-r); + vertices[5]=Point(0,-r,R); + vertices[6]=Point(0,0,R+r); + vertices[7]=Point(0,r,R); + vertices[8]=Point(-(R-r),0,0); + vertices[9]=Point(-R,-r,0); + vertices[10]=Point(-(R+r),0,0); + vertices[11]=Point(-R, r,0); + vertices[12]=Point(0,0,-(R-r)); + vertices[13]=Point(0,-r,-R); + vertices[14]=Point(0,0,-(R+r)); + vertices[15]=Point(0,r,-R); + + std::vector > cells (16); + //Right Hand Orientation + cells[0].vertices[0] = 0; + cells[0].vertices[1] = 4; + cells[0].vertices[2] = 7; + cells[0].vertices[3] = 3; + cells[0].material_id = 0; + + cells[1].vertices[0] = 1; + cells[1].vertices[1] = 5; + cells[1].vertices[2] = 4; + cells[1].vertices[3] = 0; + cells[1].material_id = 0; + + cells[2].vertices[0] = 2; + cells[2].vertices[1] = 6; + cells[2].vertices[2] = 5; + cells[2].vertices[3] = 1; + cells[2].material_id = 0; + + cells[3].vertices[0] = 3; + cells[3].vertices[1] = 7; + cells[3].vertices[2] = 6; + cells[3].vertices[3] = 2; + cells[3].material_id = 0; + + cells[4].vertices[0] = 4; + cells[4].vertices[1] = 8; + cells[4].vertices[2] = 11; + cells[4].vertices[3] = 7; + cells[4].material_id = 0; + + cells[5].vertices[0] = 5; + cells[5].vertices[1] = 9; + cells[5].vertices[2] = 8; + cells[5].vertices[3] = 4; + cells[5].material_id = 0; + + cells[6].vertices[0] = 6; + cells[6].vertices[1] = 10; + cells[6].vertices[2] = 9; + cells[6].vertices[3] = 5; + cells[6].material_id = 0; + + cells[7].vertices[0] = 7; + cells[7].vertices[1] = 11; + cells[7].vertices[2] = 10; + cells[7].vertices[3] = 6; + cells[7].material_id = 0; + + cells[8].vertices[0] = 8; + cells[8].vertices[1] = 12; + cells[8].vertices[2] = 15; + cells[8].vertices[3] = 11; + cells[8].material_id = 0; + + cells[9].vertices[0] = 9; + cells[9].vertices[1] = 13; + cells[9].vertices[2] = 12; + cells[9].vertices[3] = 8; + cells[9].material_id = 0; + + cells[10].vertices[0] = 10; + cells[10].vertices[1] = 14; + cells[10].vertices[2] = 13; + cells[10].vertices[3] = 9; + cells[10].material_id = 0; + + cells[11].vertices[0] = 11; + cells[11].vertices[1] = 15; + cells[11].vertices[2] = 14; + cells[11].vertices[3] = 10; + cells[11].material_id = 0; + + cells[12].vertices[0] = 12; + cells[12].vertices[1] = 0; + cells[12].vertices[2] = 3; + cells[12].vertices[3] = 15; + cells[12].material_id = 0; + + cells[13].vertices[0] = 13; + cells[13].vertices[1] = 1; + cells[13].vertices[2] = 0; + cells[13].vertices[3] = 12; + cells[13].material_id = 0; + + cells[14].vertices[0] = 14; + cells[14].vertices[1] = 2; + cells[14].vertices[2] = 1; + cells[14].vertices[3] = 13; + cells[14].material_id = 0; + + cells[15].vertices[0] = 15; + cells[15].vertices[1] = 3; + cells[15].vertices[2] = 2; + cells[15].vertices[3] = 14; + cells[15].material_id = 0; + + // Must call this to be able to create a + // correct triangulation in dealii, read + // GridReordering<> doc + GridReordering::reorder_cells (cells); + tria.create_triangulation_compatibility (vertices, cells, SubCellData()); + } - // wipe material id - cells[x].material_id = 0; - } - break; - case 2: - { - // Shorthand - const size_type n_dy = n_subdivisions[1]; - const size_type n_dx = n_subdivisions[0]; +// Implementation for 2D only + template<> + void + parallelogram (Triangulation<2> &tria, + const Point<2> (&corners)[2], + const bool colorize) + { + std::vector > vertices (GeometryInfo<2>::vertices_per_cell); + + vertices[1] = corners[0]; + vertices[2] = corners[1]; + vertices[3] = vertices[1] + vertices[2]; + // Prepare cell data + std::vector > cells (1); + for (unsigned int i=0; i::vertices_per_cell; ++i) + cells[0].vertices[i] = i; + cells[0].material_id = 0; + + tria.create_triangulation (vertices, cells, SubCellData()); + + // Assign boundary indicators + if (colorize) + colorize_hyper_rectangle (tria); + } + + + template<> + void + parallelogram (Triangulation<2> &tria, + const Tensor<2,2> &corners, + const bool colorize) + { + // simply pass everything to the other function of same name + const Point<2> x[2] = { corners[0], corners[1] }; + parallelogram (tria, x, colorize); + } + + + +// Parallelepiped implementation in 1d, 2d, and 3d. @note The +// implementation in 1d is similar to hyper_rectangle(), and in 2d is +// similar to parallelogram(). +// +// The GridReordering::reorder_grid is made use of towards the end of +// this function. Thus the triangulation is explicitly constructed for +// all dim here since it is slightly different in that respect +// (cf. hyper_rectangle(), parallelogram()). + template + void + parallelepiped (Triangulation &tria, + const Point (&corners) [dim], + const bool colorize) + { + // Check that none of the user defined vertices overlap + for (unsigned int i=0; i > vertices (GeometryInfo::vertices_per_cell); - for (size_type y=0; y > cells (1); + for (unsigned int i=0; i::vertices_per_cell; ++i) + cells[0].vertices[i] = i; + cells[0].material_id = 0; + + // Check ordering of vertices and create triangulation + GridReordering::reorder_cells (cells); + tria.create_triangulation (vertices, cells, SubCellData()); + + // Finally assign boundary indicators according to hyper_rectangle + if (colorize) + colorize_hyper_rectangle (tria); + } + + template + void + subdivided_parallelepiped (Triangulation &tria, + const unsigned int n_subdivisions, + const Point (&corners) [dim], + const bool colorize) + { + // Equalise number of subdivisions in each dim-direction, heir + // validity will be checked later + unsigned int (n_subdivisions_) [dim]; + for (unsigned int i=0; i + void + subdivided_parallelepiped (Triangulation &tria, + const unsigned int ( n_subdivisions) [dim], + const Point (&corners) [dim], + const bool colorize) + { + // Zero n_subdivisions is the origin only, which makes no sense + for (unsigned int i=0; i0, ExcInvalidRepetitions(n_subdivisions[i])); + + // Check corners do not overlap (unique) + for (unsigned int i=0; i (delta) [dim]; + + for (unsigned int i=0; i > points; + + switch (dim) + { + case 1: + for (unsigned int x=0; x<=n_subdivisions[0]; ++x) + points.push_back (Point (x*delta[0])); + break; + + case 2: + for (unsigned int y=0; y<=n_subdivisions[1]; ++y) + for (unsigned int x=0; x<=n_subdivisions[0]; ++x) + points.push_back (Point (x*delta[0] + y*delta[1])); + break; + + case 3: + for (unsigned int z=0; z<=n_subdivisions[2]; ++z) + for (unsigned int y=0; y<=n_subdivisions[1]; ++y) + for (unsigned int x=0; x<=n_subdivisions[0]; ++x) + points.push_back (Point (x*delta[0] + y*delta[1] + z*delta[2])); + break; + + default: + Assert (false, ExcNotImplemented()); + } + + // Prepare cell data + unsigned int n_cells = 1; + for (unsigned int i=0; i > cells (n_cells); + + // Create fixed ordering of + switch (dim) + { + case 1: + for (unsigned int x=0; x -void -GridGenerator::subdivided_hyper_cube (Triangulation &tria, - const unsigned int repetitions, - const double left, - const double right) -{ - Assert (repetitions >= 1, ExcInvalidRepetitions(repetitions)); - Assert (left < right, - ExcMessage ("Invalid left-to-right bounds of hypercube")); - - // first generate the necessary - // points - const double delta = (right-left)/repetitions; - std::vector > points; - switch (dim) - { - case 1: - for (unsigned int x=0; x<=repetitions; ++x) - points.push_back (Point (left+x*delta)); - break; - case 2: - for (unsigned int y=0; y<=repetitions; ++y) + template + void + subdivided_hyper_cube (Triangulation &tria, + const unsigned int repetitions, + const double left, + const double right) + { + Assert (repetitions >= 1, ExcInvalidRepetitions(repetitions)); + Assert (left < right, + ExcMessage ("Invalid left-to-right bounds of hypercube")); + + // first generate the necessary + // points + const double delta = (right-left)/repetitions; + std::vector > points; + switch (dim) + { + case 1: for (unsigned int x=0; x<=repetitions; ++x) - points.push_back (Point (left+x*delta, - left+y*delta)); - break; + points.push_back (Point (left+x*delta)); + break; - case 3: - for (unsigned int z=0; z<=repetitions; ++z) + case 2: for (unsigned int y=0; y<=repetitions; ++y) for (unsigned int x=0; x<=repetitions; ++x) points.push_back (Point (left+x*delta, - left+y*delta, - left+z*delta)); - break; - - default: - Assert (false, ExcNotImplemented()); - } - - // next create the cells - // Prepare cell data - std::vector > cells; - // Define these as abbreviations - // for the step sizes below. The - // number of points in a single - // direction is repetitions+1 - const unsigned int dy = repetitions+1; - const unsigned int dz = dy*dy; - switch (dim) - { - case 1: - cells.resize (repetitions); - for (unsigned int x=0; x (left+x*delta, + left+y*delta, + left+z*delta)); + break; + + default: + Assert (false, ExcNotImplemented()); + } - case 2: - cells.resize (repetitions*repetitions); - for (unsigned int y=0; y > cells; + // Define these as abbreviations + // for the step sizes below. The + // number of points in a single + // direction is repetitions+1 + const unsigned int dy = repetitions+1; + const unsigned int dz = dy*dy; + switch (dim) + { + case 1: + cells.resize (repetitions); for (unsigned int x=0; x -void -GridGenerator::subdivided_hyper_rectangle ( - Triangulation &tria, - const std::vector &repetitions, - const Point &p_1, - const Point &p_2, - const bool colorize) -{ - // contributed by Joerg R. Weimar - // (j.weimar@jweimar.de) 2003 - Assert(repetitions.size() == dim, - ExcInvalidRepetitionsDimension(dim)); - // First, normalize input such that - // p1 is lower in all coordinate - // directions. - Point p1(p_1); - Point p2(p_2); - - for (unsigned int i=0; i p2(i)) - std::swap (p1(i), p2(i)); - - // then check that all repetitions - // are >= 1, and calculate deltas - // convert repetitions from double - // to int by taking the ceiling. - Point delta; - - for (unsigned int i=0; i= 1, ExcInvalidRepetitions(repetitions[i])); + template + void + subdivided_hyper_rectangle ( + Triangulation &tria, + const std::vector &repetitions, + const Point &p_1, + const Point &p_2, + const bool colorize) + { + // contributed by Joerg R. Weimar + // (j.weimar@jweimar.de) 2003 + Assert(repetitions.size() == dim, + ExcInvalidRepetitionsDimension(dim)); + // First, normalize input such that + // p1 is lower in all coordinate + // directions. + Point p1(p_1); + Point p2(p_2); + + for (unsigned int i=0; i p2(i)) + std::swap (p1(i), p2(i)); - delta[i] = (p2[i]-p1[i])/repetitions[i]; - } + // then check that all repetitions + // are >= 1, and calculate deltas + // convert repetitions from double + // to int by taking the ceiling. + Point delta; - // then generate the necessary - // points - std::vector > points; - switch (dim) - { - case 1: - for (unsigned int x=0; x<=repetitions[0]; ++x) - points.push_back (Point (p1[0]+x*delta[0])); - break; + for (unsigned int i=0; i= 1, ExcInvalidRepetitions(repetitions[i])); + + delta[i] = (p2[i]-p1[i])/repetitions[i]; + } - case 2: - for (unsigned int y=0; y<=repetitions[1]; ++y) + // then generate the necessary + // points + std::vector > points; + switch (dim) + { + case 1: for (unsigned int x=0; x<=repetitions[0]; ++x) - points.push_back (Point (p1[0]+x*delta[0], - p1[1]+y*delta[1])); - break; + points.push_back (Point (p1[0]+x*delta[0])); + break; - case 3: - for (unsigned int z=0; z<=repetitions[2]; ++z) + case 2: for (unsigned int y=0; y<=repetitions[1]; ++y) for (unsigned int x=0; x<=repetitions[0]; ++x) points.push_back (Point (p1[0]+x*delta[0], - p1[1]+y*delta[1], - p1[2]+z*delta[2])); - break; - - default: - Assert (false, ExcNotImplemented()); - } - - // next create the cells - // Prepare cell data - std::vector > cells; - switch (dim) - { - case 1: - { - cells.resize (repetitions[0]); - for (unsigned int x=0; x (p1[0]+x*delta[0], + p1[1]+y*delta[1], + p1[2]+z*delta[2])); + break; + + default: + Assert (false, ExcNotImplemented()); + } - case 2: - { - cells.resize (repetitions[1]*repetitions[0]); - for (unsigned int y=0; y > cells; + switch (dim) + { + case 1: + { + cells.resize (repetitions[0]); for (unsigned int x=0; x 0, - ExcMessage ("The distance between corner points must be positive.")) - - // actual code is external since - // 1-D is different from 2/3D. - colorize_subdivided_hyper_rectangle (tria, p1, p2, epsilon); - } -} + } + default: + Assert (false, ExcNotImplemented()); + } + tria.create_triangulation (points, cells, SubCellData()); -template -void -GridGenerator::subdivided_hyper_rectangle( - Triangulation &tria, - const std::vector > &step_sz, - const Point &p_1, - const Point &p_2, - const bool colorize) -{ - // contributed by Joerg R. Weimar - // (j.weimar@jweimar.de) 2003 - // modified by Yaqi Wang 2006 - Assert(step_sz.size() == dim, - ExcInvalidRepetitionsDimension(dim)); - - - // First, normalize input such that - // p1 is lower in all coordinate - // directions. - - // and check the consistency of - // step sizes, i.e. that they all - // add up to the sizes specified by - // p_1 and p_2 - Point p1(p_1); - Point p2(p_2); - std::vector< std::vector > step_sizes(step_sz); - - for (unsigned int i=0; i p2(i)) - { - std::swap (p1(i), p2(i)); - std::reverse (step_sizes[i].begin(), step_sizes[i].end()); - } + if (colorize) + { + // to colorize, run through all + // faces of all cells and set + // boundary indicator to the + // correct value if it was 0. + + // use a large epsilon to + // compare numbers to avoid + // roundoff problems. + const double epsilon + = 0.01 * *std::min_element (&delta[0], &delta[0]+dim); + Assert (epsilon > 0, + ExcMessage ("The distance between corner points must be positive.")) + + // actual code is external since + // 1-D is different from 2/3D. + colorize_subdivided_hyper_rectangle (tria, p1, p2, epsilon); + } + } - double x = 0; - for (size_type j=0; j > points; - switch (dim) - { - case 1: - { - double x=0; - for (size_type i=0; ; ++i) - { - points.push_back (Point (p1[0]+x)); - - // form partial sums. in - // the last run through - // avoid accessing - // non-existent values - // and exit early instead - if (i == step_sizes[0].size()) - break; + template + void + subdivided_hyper_rectangle( + Triangulation &tria, + const std::vector > &step_sz, + const Point &p_1, + const Point &p_2, + const bool colorize) + { + // contributed by Joerg R. Weimar + // (j.weimar@jweimar.de) 2003 + // modified by Yaqi Wang 2006 + Assert(step_sz.size() == dim, + ExcInvalidRepetitionsDimension(dim)); + + + // First, normalize input such that + // p1 is lower in all coordinate + // directions. + + // and check the consistency of + // step sizes, i.e. that they all + // add up to the sizes specified by + // p_1 and p_2 + Point p1(p_1); + Point p2(p_2); + std::vector< std::vector > step_sizes(step_sz); + + for (unsigned int i=0; i p2(i)) + { + std::swap (p1(i), p2(i)); + std::reverse (step_sizes[i].begin(), step_sizes[i].end()); + } - x += step_sizes[0][i]; - } - break; - } + double x = 0; + for (unsigned int j=0; j (p1[0]+x, - p1[1]+y)); - if (i == step_sizes[0].size()) - break; - x += step_sizes[0][i]; - } + // then generate the necessary + // points + std::vector > points; + switch (dim) + { + case 1: + { + double x=0; + for (unsigned int i=0; ; ++i) + { + points.push_back (Point (p1[0]+x)); - if (j == step_sizes[1].size()) - break; + // form partial sums. in + // the last run through + // avoid accessing + // non-existent values + // and exit early instead + if (i == step_sizes[0].size()) + break; - y += step_sizes[1][j]; - } - break; + x += step_sizes[0][i]; + } + break; + } - } - case 3: - { - double z=0; - for (size_type k=0; ; ++k) - { - double y=0; - for (size_type j=0; ; ++j) - { - double x=0; - for (size_type i=0; ; ++i) - { - points.push_back (Point (p1[0]+x, - p1[1]+y, - p1[2]+z)); - if (i == step_sizes[0].size()) - break; + case 2: + { + double y=0; + for (unsigned int j=0; ; ++j) + { + double x=0; + for (unsigned int i=0; ; ++i) + { + points.push_back (Point (p1[0]+x, + p1[1]+y)); + if (i == step_sizes[0].size()) + break; - x += step_sizes[0][i]; - } + x += step_sizes[0][i]; + } - if (j == step_sizes[1].size()) - break; + if (j == step_sizes[1].size()) + break; - y += step_sizes[1][j]; - } + y += step_sizes[1][j]; + } + break; - if (k == step_sizes[2].size()) - break; + } + case 3: + { + double z=0; + for (unsigned int k=0; ; ++k) + { + double y=0; + for (unsigned int j=0; ; ++j) + { + double x=0; + for (unsigned int i=0; ; ++i) + { + points.push_back (Point (p1[0]+x, + p1[1]+y, + p1[2]+z)); + if (i == step_sizes[0].size()) + break; - z += step_sizes[2][k]; - } - break; - } + x += step_sizes[0][i]; + } - default: - Assert (false, ExcNotImplemented()); - } + if (j == step_sizes[1].size()) + break; - // next create the cells - // Prepare cell data - std::vector > cells; - switch (dim) - { - case 1: - { - cells.resize (step_sizes[0].size()); - for (size_type x=0; x > cells; + switch (dim) + { + case 1: + { + cells.resize (step_sizes[0].size()); + for (unsigned int x=0; x -void -GridGenerator::subdivided_hyper_rectangle ( - Triangulation<1> &tria, - const std::vector< std::vector > &spacing, - const Point<1> &p, - const Table<1,types::material_id> &material_id, - const bool colorize) -{ - // contributed by Yaqi Wang 2006 - Assert(spacing.size() == 1, - ExcInvalidRepetitionsDimension(1)); - const size_type n_cells = material_id.size(0); - Assert(spacing[0].size() == n_cells, - ExcInvalidRepetitionsDimension(1)); + template <> + void + subdivided_hyper_rectangle ( + Triangulation<1> &tria, + const std::vector< std::vector > &spacing, + const Point<1> &p, + const Table<1,types::material_id> &material_id, + const bool colorize) + { + // contributed by Yaqi Wang 2006 + Assert(spacing.size() == 1, + ExcInvalidRepetitionsDimension(1)); - double delta = std::numeric_limits::max(); - for (size_type i=0; i= 0, ExcInvalidRepetitions(-1)); - delta = std::min (delta, spacing[0][i]); - } + const unsigned int n_cells = material_id.size(0); - // generate the necessary points - std::vector > points; - double ax = p[0]; - for (size_type x=0; x<=n_cells; ++x) - { - points.push_back (Point<1> (ax)); - if (x > cells(n_val_cells); - size_type id = 0; - for (size_type x=0; x::max(); + for (unsigned int i=0; i= 0, ExcInvalidRepetitions(-1)); + delta = std::min (delta, spacing[0][i]); } - // create triangulation - SubCellData t; - GridTools::delete_unused_vertices (points, cells, t); - tria.create_triangulation (points, cells, t); + // generate the necessary points + std::vector > points; + double ax = p[0]; + for (unsigned int x=0; x<=n_cells; ++x) + { + points.push_back (Point<1> (ax)); + if (x > cells(n_val_cells); + unsigned int id = 0; + for (unsigned int x=0; x -void -GridGenerator::subdivided_hyper_rectangle ( - Triangulation<2> &tria, - const std::vector< std::vector > &spacing, - const Point<2> &p, - const Table<2,types::material_id> &material_id, - const bool colorize) -{ - // contributed by Yaqi Wang 2006 - Assert(spacing.size() == 2, - ExcInvalidRepetitionsDimension(2)); - - std::vector repetitions(2); - size_type n_cells = 1; - double delta = std::numeric_limits::max(); - for (unsigned int i=0; i<2; i++) - { - repetitions[i] = spacing[i].size(); - n_cells *= repetitions[i]; - for (size_type j=0; j= 0, ExcInvalidRepetitions(-1)); - delta = std::min (delta, spacing[i][j]); - } - Assert(material_id.size(i) == repetitions[i], - ExcInvalidRepetitionsDimension(i)); - } - // generate the necessary points - std::vector > points; - double ay = p[1]; - for (size_type y=0; y<=repetitions[1]; ++y) - { - double ax = p[0]; - for (size_type x=0; x<=repetitions[0]; ++x) - { - points.push_back (Point<2> (ax,ay)); - if (x + void + subdivided_hyper_rectangle ( + Triangulation<2> &tria, + const std::vector< std::vector > &spacing, + const Point<2> &p, + const Table<2,types::material_id> &material_id, + const bool colorize) + { + // contributed by Yaqi Wang 2006 + Assert(spacing.size() == 2, + ExcInvalidRepetitionsDimension(2)); + + std::vector repetitions(2); + unsigned int n_cells = 1; + double delta = std::numeric_limits::max(); + for (unsigned int i=0; i<2; i++) + { + repetitions[i] = spacing[i].size(); + n_cells *= repetitions[i]; + for (unsigned int j=0; j= 0, ExcInvalidRepetitions(-1)); + delta = std::min (delta, spacing[i][j]); + } + Assert(material_id.size(i) == repetitions[i], + ExcInvalidRepetitionsDimension(i)); + } - // create the cells - size_type n_val_cells = 0; - for (size_type i=0; i > cells(n_val_cells); - size_type id = 0; - for (size_type y=0; y > points; + double ay = p[1]; + for (unsigned int y=0; y<=repetitions[1]; ++y) + { + double ax = p[0]; + for (unsigned int x=0; x<=repetitions[0]; ++x) + { + points.push_back (Point<2> (ax,ay)); + if (x > cells(n_val_cells); + unsigned int id = 0; + for (unsigned int y=0; y::cell_iterator cell = tria.begin(), - endc = tria.end(); - for (; cell !=endc; ++cell) - { - Point<2> cell_center = cell->center(); - for (unsigned int f=0; f::faces_per_cell; ++f) - if (cell->face(f)->boundary_indicator() == 0) - { - Point<2> face_center = cell->face(f)->center(); - for (unsigned int i=0; i<2; ++i) - { - if (face_center[i]face(f)->set_boundary_indicator(i*2); - if (face_center[i]>cell_center[i]+eps) - cell->face(f)->set_boundary_indicator(i*2+1); - } - } - } - } -} + // create triangulation + SubCellData t; + GridTools::delete_unused_vertices (points, cells, t); + tria.create_triangulation (points, cells, t); -template <> -void -GridGenerator::subdivided_hyper_rectangle ( - Triangulation<3> &tria, - const std::vector< std::vector > &spacing, - const Point<3> &p, - const Table<3,types::material_id> &material_id, - const bool colorize) -{ - // contributed by Yaqi Wang 2006 - const unsigned int dim = 3; + // set boundary indicator + if (colorize) + { + double eps = 0.01 * delta; + Triangulation<2>::cell_iterator cell = tria.begin(), + endc = tria.end(); + for (; cell !=endc; ++cell) + { + Point<2> cell_center = cell->center(); + for (unsigned int f=0; f::faces_per_cell; ++f) + if (cell->face(f)->boundary_indicator() == 0) + { + Point<2> face_center = cell->face(f)->center(); + for (unsigned int i=0; i<2; ++i) + { + if (face_center[i]face(f)->set_boundary_indicator(i*2); + if (face_center[i]>cell_center[i]+eps) + cell->face(f)->set_boundary_indicator(i*2+1); + } + } + } + } + } - Assert(spacing.size() == dim, - ExcInvalidRepetitionsDimension(dim)); - std::vector repetitions(dim); - size_type n_cells = 1; - double delta = std::numeric_limits::max(); - for (unsigned int i=0; i= 0, ExcInvalidRepetitions(-1)); - delta = std::min (delta, spacing[i][j]); - } - Assert(material_id.size(i) == repetitions[i], - ExcInvalidRepetitionsDimension(i)); - } + template <> + void + subdivided_hyper_rectangle ( + Triangulation<3> &tria, + const std::vector< std::vector > &spacing, + const Point<3> &p, + const Table<3,types::material_id> &material_id, + const bool colorize) + { + // contributed by Yaqi Wang 2006 + const unsigned int dim = 3; - // generate the necessary points - std::vector > points; - double az = p[2]; - for (size_type z=0; z<=repetitions[2]; ++z) - { - double ay = p[1]; - for (size_type y=0; y<=repetitions[1]; ++y) - { - double ax = p[0]; - for (size_type x=0; x<=repetitions[0]; ++x) + Assert(spacing.size() == dim, + ExcInvalidRepetitionsDimension(dim)); + + std::vector repetitions(dim); + unsigned int n_cells = 1; + double delta = std::numeric_limits::max(); + for (unsigned int i=0; i= 0, ExcInvalidRepetitions(-1)); + delta = std::min (delta, spacing[i][j]); + } + Assert(material_id.size(i) == repetitions[i], + ExcInvalidRepetitionsDimension(i)); + } + + // generate the necessary points + std::vector > points; + double az = p[2]; + for (unsigned int z=0; z<=repetitions[2]; ++z) + { + double ay = p[1]; + for (unsigned int y=0; y<=repetitions[1]; ++y) + { + double ax = p[0]; + for (unsigned int x=0; x<=repetitions[0]; ++x) + { + points.push_back (Point (ax,ay,az)); + if (x > cells(n_val_cells); + unsigned int id = 0; + const unsigned int n_x = (repetitions[0]+1); + const unsigned int n_xy = (repetitions[0]+1)*(repetitions[1]+1); + for (unsigned int z=0; z (ax,ay,az)); - if (x > cells(n_val_cells); - size_type id = 0; - const size_type n_x = (repetitions[0]+1); - const size_type n_xy = (repetitions[0]+1)*(repetitions[1]+1); - for (size_type z=0; z1) + { + double eps = 0.01 * delta; + Triangulation::cell_iterator cell = tria.begin(), + endc = tria.end(); + for (; cell !=endc; ++cell) { - cells[id].vertices[0] = z*n_xy + y*n_x + x; - cells[id].vertices[1] = z*n_xy + y*n_x + x+1; - cells[id].vertices[2] = z*n_xy + (y+1)*n_x + x; - cells[id].vertices[3] = z*n_xy + (y+1)*n_x + x+1; - cells[id].vertices[4] = (z+1)*n_xy + y*n_x + x; - cells[id].vertices[5] = (z+1)*n_xy + y*n_x + x+1; - cells[id].vertices[6] = (z+1)*n_xy + (y+1)*n_x + x; - cells[id].vertices[7] = (z+1)*n_xy + (y+1)*n_x + x+1; - cells[id].material_id = material_id[x][y][z]; - id++; + Point cell_center = cell->center(); + for (unsigned int f=0; f::faces_per_cell; ++f) + if (cell->face(f)->boundary_indicator() == 0) + { + Point face_center = cell->face(f)->center(); + for (unsigned int i=0; iface(f)->set_boundary_indicator(i*2); + if (face_center[i]>cell_center[i]+eps) + cell->face(f)->set_boundary_indicator(i*2+1); + } + } } + } + } - // create triangulation - SubCellData t; - GridTools::delete_unused_vertices (points, cells, t); - tria.create_triangulation (points, cells, t); - // set boundary indicator - if (colorize && dim>1) - { - double eps = 0.01 * delta; - Triangulation::cell_iterator cell = tria.begin(), - endc = tria.end(); - for (; cell !=endc; ++cell) - { - Point cell_center = cell->center(); - for (unsigned int f=0; f::faces_per_cell; ++f) - if (cell->face(f)->boundary_indicator() == 0) - { - Point face_center = cell->face(f)->center(); - for (unsigned int i=0; iface(f)->set_boundary_indicator(i*2); - if (face_center[i]>cell_center[i]+eps) - cell->face(f)->set_boundary_indicator(i*2+1); - } - } - } - } -} + template <> + void hyper_cube_slit (Triangulation<1> &, + const double, + const double, + const bool) + { + Assert (false, ExcNotImplemented()); + } -template <> -void -GridGenerator::colorize_subdivided_hyper_rectangle ( - Triangulation<1> &tria, - const Point<1> &, - const Point<1> &, - const double) -{ - for (Triangulation<1>::cell_iterator cell = tria.begin(); - cell != tria.end(); ++cell) - if (cell->center()(0) > 0) - cell->set_material_id(1); - // boundary indicators are set to - // 0 (left) and 1 (right) by default. -} + template <> + void enclosed_hyper_cube (Triangulation<1> &, + const double, + const double, + const double, + const bool) + { + Assert (false, ExcNotImplemented()); + } -template -void -GridGenerator::colorize_subdivided_hyper_rectangle (Triangulation &tria, - const Point &p1, - const Point &p2, - const double epsilon) -{ + template <> + void hyper_L (Triangulation<1> &, + const double, + const double) + { + Assert (false, ExcNotImplemented()); + } - // run through all faces and check - // if one of their center coordinates matches - // one of the corner points. Comparisons - // are made using an epsilon which - // should be smaller than the smallest cell - // diameter. - typename Triangulation::face_iterator face = tria.begin_face(), - endface = tria.end_face(); - for (; face!=endface; ++face) - { - if (face->boundary_indicator() == 0) - { - const Point center (face->center()); - if (std::abs(center(0)-p1[0]) < epsilon) - face->set_boundary_indicator(0); - else if (std::abs(center(0) - p2[0]) < epsilon) - face->set_boundary_indicator(1); - else if (dim > 1 && std::abs(center(1) - p1[1]) < epsilon) - face->set_boundary_indicator(2); - else if (dim > 1 && std::abs(center(1) - p2[1]) < epsilon) - face->set_boundary_indicator(3); - else if (dim > 2 && std::abs(center(2) - p1[2]) < epsilon) - face->set_boundary_indicator(4); - else if (dim > 2 && std::abs(center(2) - p2[2]) < epsilon) - face->set_boundary_indicator(5); - else - // triangulation says it - // is on the boundary, - // but we could not find - // on which boundary. - Assert (false, ExcInternalError()); - } - } - for (typename Triangulation::cell_iterator cell = tria.begin(); - cell != tria.end(); ++cell) - { - char id = 0; - for (unsigned int d=0; dcenter()(d) > 0) id += 1 << d; - cell->set_material_id(id); - } -} + template <> + void hyper_ball (Triangulation<1> &, + const Point<1> &, + const double) + { + Assert (false, ExcNotImplemented()); + } -template <> -void GridGenerator::hyper_cube_slit (Triangulation<1> &, - const double, - const double, - const bool) -{ - Assert (false, ExcNotImplemented()); -} + template <> + void cylinder (Triangulation<1> &, + const double, + const double) + { + Assert (false, ExcNotImplemented()); + } -template <> -void GridGenerator::enclosed_hyper_cube (Triangulation<1> &, - const double, - const double, - const double, - const bool) -{ - Assert (false, ExcNotImplemented()); -} + template <> + void truncated_cone (Triangulation<1> &, + const double, + const double, + const double) + { + Assert (false, ExcNotImplemented()); + } -template <> -void GridGenerator::hyper_L (Triangulation<1> &, - const double, - const double) -{ - Assert (false, ExcNotImplemented()); -} + template <> + void hyper_shell (Triangulation<1> &, + const Point<1> &, + const double, + const double, + const unsigned int , + const bool) + { + Assert (false, ExcNotImplemented()); + } -template <> -void GridGenerator::hyper_ball (Triangulation<1> &, - const Point<1> &, - const double) -{ - Assert (false, ExcNotImplemented()); -} + template <> + void cylinder_shell (Triangulation<1> &, + const double, + const double, + const double, + const unsigned int , + const unsigned int ) + { + Assert (false, ExcNotImplemented()); + } + template <> + void + half_hyper_ball (Triangulation<1> &, + const Point<1> &, + const double) + { + Assert (false, ExcNotImplemented()); + } -template <> -void GridGenerator::cylinder (Triangulation<1> &, - const double, - const double) -{ - Assert (false, ExcNotImplemented()); -} + template <> + void + half_hyper_shell (Triangulation<1> &, + const Point<1> &, + const double, + const double, + const unsigned int , + const bool) + { + Assert (false, ExcNotImplemented()); + } + + template <> + void quarter_hyper_shell (Triangulation<1> &, + const Point<1> &, + const double, + const double, + const unsigned int , + const bool) + { + Assert (false, ExcNotImplemented()); + } + + template <> + void enclosed_hyper_cube (Triangulation<2> &tria, + const double left, + const double right, + const double thickness, + const bool colorize) + { + Assert(left > vertices(16); + double coords[4]; + coords[0] = left-thickness; + coords[1] = left; + coords[2] = right; + coords[3] = right+thickness; + + unsigned int k=0; + for (unsigned int i0=0; i0<4; ++i0) + for (unsigned int i1=0; i1<4; ++i1) + vertices[k++] = Point<2>(coords[i1], coords[i0]); + + const types::material_id materials[9] = { 5, 4, 6, + 1, 0, 2, + 9, 8,10 + }; + + std::vector > cells(9); + k = 0; + for (unsigned int i0=0; i0<3; ++i0) + for (unsigned int i1=0; i1<3; ++i1) + { + cells[k].vertices[0] = i1+4*i0; + cells[k].vertices[1] = i1+4*i0+1; + cells[k].vertices[2] = i1+4*i0+4; + cells[k].vertices[3] = i1+4*i0+5; + if (colorize) + cells[k].material_id = materials[k]; + ++k; + } + tria.create_triangulation (vertices, + cells, + SubCellData()); // no boundary information + } -template <> -void GridGenerator::truncated_cone (Triangulation<1> &, - const double, - const double, - const double) -{ - Assert (false, ExcNotImplemented()); -} +// Implementation for 2D only + template <> + void + hyper_cube_slit (Triangulation<2> &tria, + const double left, + const double right, + const bool colorize) + { + const double rl2=(right+left)/2; + const Point<2> vertices[10] = { Point<2>(left, left ), + Point<2>(rl2, left ), + Point<2>(rl2, rl2 ), + Point<2>(left, rl2 ), + Point<2>(right,left ), + Point<2>(right,rl2 ), + Point<2>(rl2, right), + Point<2>(left, right), + Point<2>(right,right), + Point<2>(rl2, left ) + }; + const int cell_vertices[4][4] = { { 0,1,3,2 }, + { 9,4,2,5 }, + { 3,2,7,6 }, + { 2,5,6,8 } + }; + std::vector > cells (4, CellData<2>()); + for (unsigned int i=0; i<4; ++i) + { + for (unsigned int j=0; j<4; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[10]), + cells, + SubCellData()); // no boundary information + if (colorize) + { + Triangulation<2>::cell_iterator cell = tria.begin(); + cell->face(1)->set_boundary_indicator(1); + ++cell; + cell->face(3)->set_boundary_indicator(2); + } + } -template <> -void GridGenerator::hyper_shell (Triangulation<1> &, - const Point<1> &, - const double, - const double, - const size_type , - const bool) -{ - Assert (false, ExcNotImplemented()); -} -template <> -void GridGenerator::colorize_hyper_shell (Triangulation<1> &, - const Point<1> &, - const double, - const double) -{ - Assert (false, ExcNotImplemented()); -} + template <> + void truncated_cone (Triangulation<2> &triangulation, + const double radius_0, + const double radius_1, + const double half_length) + { + Point<2> vertices_tmp[4]; + vertices_tmp[0] = Point<2> (-half_length, -radius_0); + vertices_tmp[1] = Point<2> (half_length, -radius_1); + vertices_tmp[2] = Point<2> (-half_length, radius_0); + vertices_tmp[3] = Point<2> (half_length, radius_1); -template <> -void GridGenerator::cylinder_shell (Triangulation<1> &, - const double, - const double, - const double, - const size_type , - const size_type ) -{ - Assert (false, ExcNotImplemented()); -} + const std::vector > vertices (&vertices_tmp[0], &vertices_tmp[4]); + unsigned int cell_vertices[1][GeometryInfo<2>::vertices_per_cell]; + for (unsigned int i = 0; i < GeometryInfo<2>::vertices_per_cell; ++i) + cell_vertices[0][i] = i; -template <> -void -GridGenerator::half_hyper_ball (Triangulation<1> &, - const Point<1> &, - const double) -{ - Assert (false, ExcNotImplemented()); -} + std::vector > cells (1, CellData<2> ()); + for (unsigned int i = 0; i < GeometryInfo<2>::vertices_per_cell; ++i) + cells[0].vertices[i] = cell_vertices[0][i]; -template <> -void -GridGenerator::half_hyper_shell (Triangulation<1> &, - const Point<1> &, - const double, - const double, - const size_type , - const bool) -{ - Assert (false, ExcNotImplemented()); -} + cells[0].material_id = 0; + triangulation.create_triangulation (vertices, cells, SubCellData ()); -template <> -void GridGenerator::quarter_hyper_shell (Triangulation<1> &, - const Point<1> &, - const double, - const double, - const size_type , - const bool) -{ - Assert (false, ExcNotImplemented()); -} + Triangulation<2>::cell_iterator cell = triangulation.begin (); -template <> -void GridGenerator::enclosed_hyper_cube (Triangulation<2> &tria, - const double left, - const double right, - const double thickness, - const bool colorize) -{ - Assert(left > vertices(16); - double coords[4]; - coords[0] = left-thickness; - coords[1] = left; - coords[2] = right; - coords[3] = right+thickness; - - unsigned int k=0; - for (unsigned int i0=0; i0<4; ++i0) - for (unsigned int i1=0; i1<4; ++i1) - vertices[k++] = Point<2>(coords[i1], coords[i0]); - - const types::material_id materials[9] = { 5, 4, 6, - 1, 0, 2, - 9, 8,10 - }; - - std::vector > cells(9); - k = 0; - for (unsigned int i0=0; i0<3; ++i0) - for (unsigned int i1=0; i1<3; ++i1) - { - cells[k].vertices[0] = i1+4*i0; - cells[k].vertices[1] = i1+4*i0+1; - cells[k].vertices[2] = i1+4*i0+4; - cells[k].vertices[3] = i1+4*i0+5; - if (colorize) - cells[k].material_id = materials[k]; - ++k; - } - tria.create_triangulation (vertices, - cells, - SubCellData()); // no boundary information -} + cell->face (0)->set_boundary_indicator (1); + cell->face (1)->set_boundary_indicator (2); + + for (unsigned int i = 2; i < 4; ++i) + cell->face (i)->set_boundary_indicator (0); + } +//TODO: Colorize edges as circumference, left and right radius // Implementation for 2D only -template <> -void -GridGenerator::hyper_cube_slit (Triangulation<2> &tria, - const double left, - const double right, - const bool colorize) -{ - const double rl2=(right+left)/2; - const Point<2> vertices[10] = { Point<2>(left, left ), - Point<2>(rl2, left ), - Point<2>(rl2, rl2 ), - Point<2>(left, rl2 ), - Point<2>(right,left ), - Point<2>(right,rl2 ), - Point<2>(rl2, right), - Point<2>(left, right), - Point<2>(right,right), - Point<2>(rl2, left ) - }; - const int cell_vertices[4][4] = { { 0,1,3,2 }, - { 9,4,2,5 }, - { 3,2,7,6 }, - { 2,5,6,8 } - }; - std::vector > cells (4, CellData<2>()); - for (unsigned int i=0; i<4; ++i) - { - for (unsigned int j=0; j<4; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; + template <> + void + hyper_L (Triangulation<2> &tria, + const double a, + const double b) + { + const Point<2> vertices[8] = { Point<2> (a,a), + Point<2> ((a+b)/2,a), + Point<2> (b,a), + Point<2> (a,(a+b)/2), + Point<2> ((a+b)/2,(a+b)/2), + Point<2> (b,(a+b)/2), + Point<2> (a,b), + Point<2> ((a+b)/2,b) + }; + const int cell_vertices[3][4] = {{0, 1, 3, 4}, + {1, 2, 4, 5}, + {3, 4, 6, 7} }; - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[10]), - cells, - SubCellData()); // no boundary information - if (colorize) - { - Triangulation<2>::cell_iterator cell = tria.begin(); - cell->face(1)->set_boundary_indicator(1); - ++cell; - cell->face(3)->set_boundary_indicator(2); - } -} + std::vector > cells (3, CellData<2>()); + for (unsigned int i=0; i<3; ++i) + { + for (unsigned int j=0; j<4; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[8]), + cells, + SubCellData()); // no boundary information + } -template <> -void GridGenerator::truncated_cone (Triangulation<2> &triangulation, - const double radius_0, - const double radius_1, - const double half_length) -{ - Point<2> vertices_tmp[4]; - vertices_tmp[0] = Point<2> (-half_length, -radius_0); - vertices_tmp[1] = Point<2> (half_length, -radius_1); - vertices_tmp[2] = Point<2> (-half_length, radius_0); - vertices_tmp[3] = Point<2> (half_length, radius_1); - const std::vector > vertices (&vertices_tmp[0], &vertices_tmp[4]); - unsigned int cell_vertices[1][GeometryInfo<2>::vertices_per_cell]; +// Implementation for 2D only + template <> + void + hyper_ball (Triangulation<2> &tria, + const Point<2> &p, + const double radius) + { + // equilibrate cell sizes at + // transition from the inner part + // to the radial cells + const double a = 1./(1+std::sqrt(2.0)); + const Point<2> vertices[8] = { p+Point<2>(-1,-1) *(radius/std::sqrt(2.0)), + p+Point<2>(+1,-1) *(radius/std::sqrt(2.0)), + p+Point<2>(-1,-1) *(radius/std::sqrt(2.0)*a), + p+Point<2>(+1,-1) *(radius/std::sqrt(2.0)*a), + p+Point<2>(-1,+1) *(radius/std::sqrt(2.0)*a), + p+Point<2>(+1,+1) *(radius/std::sqrt(2.0)*a), + p+Point<2>(-1,+1) *(radius/std::sqrt(2.0)), + p+Point<2>(+1,+1) *(radius/std::sqrt(2.0)) + }; + + const int cell_vertices[5][4] = {{0, 1, 2, 3}, + {0, 2, 6, 4}, + {2, 3, 4, 5}, + {1, 7, 3, 5}, + {6, 4, 7, 5} + }; - for (unsigned int i = 0; i < GeometryInfo<2>::vertices_per_cell; ++i) - cell_vertices[0][i] = i; + std::vector > cells (5, CellData<2>()); - std::vector > cells (1, CellData<2> ()); + for (unsigned int i=0; i<5; ++i) + { + for (unsigned int j=0; j<4; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; - for (unsigned int i = 0; i < GeometryInfo<2>::vertices_per_cell; ++i) - cells[0].vertices[i] = cell_vertices[0][i]; + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[8]), + cells, + SubCellData()); // no boundary information + } - cells[0].material_id = 0; - triangulation.create_triangulation (vertices, cells, SubCellData ()); - Triangulation<2>::cell_iterator cell = triangulation.begin (); - cell->face (0)->set_boundary_indicator (1); - cell->face (1)->set_boundary_indicator (2); + template <> + void hyper_shell (Triangulation<2> &tria, + const Point<2> ¢er, + const double inner_radius, + const double outer_radius, + const unsigned int n_cells, + const bool colorize) + { + Assert ((inner_radius > 0) && (inner_radius < outer_radius), + ExcInvalidRadii ()); + + const double pi = numbers::PI; + + // determine the number of cells + // for the grid. if not provided by + // the user determine it such that + // the length of each cell on the + // median (in the middle between + // the two circles) is equal to its + // radial extent (which is the + // difference between the two + // radii) + const unsigned int N = (n_cells == 0 ? + static_cast + (std::ceil((2*pi* (outer_radius + inner_radius)/2) / + (outer_radius - inner_radius))) : + n_cells); + + // set up N vertices on the + // outer and N vertices on + // the inner circle. the + // first N ones are on the + // outer one, and all are + // numbered counter-clockwise + std::vector > vertices(2*N); + for (unsigned int i=0; i( std::cos(2*pi * i/N), + std::sin(2*pi * i/N)) * outer_radius; + vertices[i+N] = vertices[i] * (inner_radius/outer_radius); - for (unsigned int i = 2; i < 4; ++i) - cell->face (i)->set_boundary_indicator (0); -} + vertices[i] += center; + vertices[i+N] += center; + }; + std::vector > cells (N, CellData<2>()); + for (unsigned int i=0; i -void -GridGenerator::hyper_L (Triangulation<2> &tria, - const double a, - const double b) -{ - const Point<2> vertices[8] = { Point<2> (a,a), - Point<2> ((a+b)/2,a), - Point<2> (b,a), - Point<2> (a,(a+b)/2), - Point<2> ((a+b)/2,(a+b)/2), - Point<2> (b,(a+b)/2), - Point<2> (a,b), - Point<2> ((a+b)/2,b) - }; - const int cell_vertices[3][4] = {{0, 1, 3, 4}, - {1, 2, 4, 5}, - {3, 4, 6, 7} - }; - - std::vector > cells (3, CellData<2>()); - - for (unsigned int i=0; i<3; ++i) - { - for (unsigned int j=0; j<4; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; - }; + cells[i].material_id = 0; + }; - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[8]), - cells, - SubCellData()); // no boundary information -} + tria.create_triangulation ( + vertices, cells, SubCellData()); + if (colorize) + colorize_hyper_shell(tria, center, inner_radius, outer_radius); + } // Implementation for 2D only -template <> -void -GridGenerator::hyper_ball (Triangulation<2> &tria, - const Point<2> &p, - const double radius) -{ - // equilibrate cell sizes at - // transition from the inner part - // to the radial cells - const double a = 1./(1+std::sqrt(2.0)); - const Point<2> vertices[8] = { p+Point<2>(-1,-1) *(radius/std::sqrt(2.0)), - p+Point<2>(+1,-1) *(radius/std::sqrt(2.0)), - p+Point<2>(-1,-1) *(radius/std::sqrt(2.0)*a), - p+Point<2>(+1,-1) *(radius/std::sqrt(2.0)*a), - p+Point<2>(-1,+1) *(radius/std::sqrt(2.0)*a), - p+Point<2>(+1,+1) *(radius/std::sqrt(2.0)*a), - p+Point<2>(-1,+1) *(radius/std::sqrt(2.0)), - p+Point<2>(+1,+1) *(radius/std::sqrt(2.0)) - }; - - const int cell_vertices[5][4] = {{0, 1, 2, 3}, - {0, 2, 6, 4}, - {2, 3, 4, 5}, - {1, 7, 3, 5}, - {6, 4, 7, 5} - }; - - std::vector > cells (5, CellData<2>()); - - for (unsigned int i=0; i<5; ++i) - { - for (unsigned int j=0; j<4; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; - }; + template <> + void + cylinder (Triangulation<2> &tria, + const double radius, + const double half_length) + { + Point<2> p1 (-half_length, -radius); + Point<2> p2 (half_length, radius); - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[8]), - cells, - SubCellData()); // no boundary information -} + hyper_rectangle(tria, p1, p2, true); + + Triangulation<2>::face_iterator f = tria.begin_face(); + Triangulation<2>::face_iterator end = tria.end_face(); + while (f != end) + { + switch (f->boundary_indicator()) + { + case 0: + f->set_boundary_indicator(1); + break; + case 1: + f->set_boundary_indicator(2); + break; + default: + f->set_boundary_indicator(0); + break; + } + ++f; + } + } // Implementation for 2D only -template<> -void -GridGenerator::colorize_hyper_shell ( - Triangulation<2> &tria, - const Point<2> &, const double, const double) -{ - // In spite of receiving geometrical - // data, we do this only based on - // topology. - - // For the mesh based on cube, - // this is highly irregular - for (Triangulation<2>::cell_iterator cell = tria.begin(); - cell != tria.end(); ++cell) - { - Assert (cell->face(2)->at_boundary(), ExcInternalError()); - cell->face(2)->set_boundary_indicator(1); - } -} - + template <> + void cylinder_shell (Triangulation<2> &, + const double, + const double, + const double, + const unsigned int, + const unsigned int) + { + Assert (false, ExcNotImplemented()); + } -template <> -void GridGenerator::hyper_shell (Triangulation<2> &tria, - const Point<2> ¢er, - const double inner_radius, - const double outer_radius, - const size_type n_cells, - const bool colorize) -{ - Assert ((inner_radius > 0) && (inner_radius < outer_radius), - ExcInvalidRadii ()); - - const double pi = numbers::PI; - - // determine the number of cells - // for the grid. if not provided by - // the user determine it such that - // the length of each cell on the - // median (in the middle between - // the two circles) is equal to its - // radial extent (which is the - // difference between the two - // radii) - const size_type N = (n_cells == 0 ? - static_cast - (std::ceil((2*pi* (outer_radius + inner_radius)/2) / - (outer_radius - inner_radius))) : - n_cells); - - // set up N vertices on the - // outer and N vertices on - // the inner circle. the - // first N ones are on the - // outer one, and all are - // numbered counter-clockwise - std::vector > vertices(2*N); - for (size_type i=0; i( std::cos(2*pi * i/N), - std::sin(2*pi * i/N)) * outer_radius; - vertices[i+N] = vertices[i] * (inner_radius/outer_radius); - vertices[i] += center; - vertices[i+N] += center; + template <> + void + half_hyper_ball (Triangulation<2> &tria, + const Point<2> &p, + const double radius) + { + // equilibrate cell sizes at + // transition from the inner part + // to the radial cells + const double a = 1./(1+std::sqrt(2.0)); + const Point<2> vertices[8] = { p+Point<2>(0,-1) *radius, + p+Point<2>(+1,-1) *(radius/std::sqrt(2.0)), + p+Point<2>(0,-1) *(radius/std::sqrt(2.0)*a), + p+Point<2>(+1,-1) *(radius/std::sqrt(2.0)*a), + p+Point<2>(0,+1) *(radius/std::sqrt(2.0)*a), + p+Point<2>(+1,+1) *(radius/std::sqrt(2.0)*a), + p+Point<2>(0,+1) *radius, + p+Point<2>(+1,+1) *(radius/std::sqrt(2.0)) + }; + + const int cell_vertices[5][4] = {{0, 1, 2, 3}, + {2, 3, 4, 5}, + {1, 7, 3, 5}, + {6, 4, 7, 5} }; - std::vector > cells (N, CellData<2>()); - - for (size_type i=0; i > cells (4, CellData<2>()); - tria.create_triangulation ( - vertices, cells, SubCellData()); + for (unsigned int i=0; i<4; ++i) + { + for (unsigned int j=0; j<4; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; - if (colorize) - colorize_hyper_shell(tria, center, inner_radius, outer_radius); -} + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[8]), + cells, + SubCellData()); // no boundary information + Triangulation<2>::cell_iterator cell = tria.begin(); + Triangulation<2>::cell_iterator end = tria.end(); -// Implementation for 2D only -template <> -void -GridGenerator::cylinder (Triangulation<2> &tria, - const double radius, - const double half_length) -{ - Point<2> p1 (-half_length, -radius); - Point<2> p2 (half_length, radius); - hyper_rectangle(tria, p1, p2, true); + while (cell != end) + { + for (unsigned int i=0; i::faces_per_cell; ++i) + { + if (cell->face(i)->boundary_indicator() == numbers::internal_face_boundary_id) + continue; - Triangulation<2>::face_iterator f = tria.begin_face(); - Triangulation<2>::face_iterator end = tria.end_face(); - while (f != end) - { - switch (f->boundary_indicator()) - { - case 0: - f->set_boundary_indicator(1); - break; - case 1: - f->set_boundary_indicator(2); - break; - default: - f->set_boundary_indicator(0); - break; - } - ++f; - } -} + // If x is zero, then this is part of the plane + if (cell->face(i)->center()(0) < p(0)+1.e-5) + cell->face(i)->set_boundary_indicator(1); + } + ++cell; + } + } // Implementation for 2D only -template <> -void GridGenerator::cylinder_shell (Triangulation<2> &, - const double, - const double, - const double, - const size_type, - const size_type) -{ - Assert (false, ExcNotImplemented()); -} + template <> + void + half_hyper_shell (Triangulation<2> &tria, + const Point<2> ¢er, + const double inner_radius, + const double outer_radius, + const unsigned int n_cells, + const bool colorize) + { + Assert ((inner_radius > 0) && (inner_radius < outer_radius), + ExcInvalidRadii ()); + + const double pi = numbers::PI; + // determine the number of cells + // for the grid. if not provided by + // the user determine it such that + // the length of each cell on the + // median (in the middle between + // the two circles) is equal to its + // radial extent (which is the + // difference between the two + // radii) + const unsigned int N = (n_cells == 0 ? + static_cast + (std::ceil((pi* (outer_radius + inner_radius)/2) / + (outer_radius - inner_radius))) : + n_cells); + + // set up N+1 vertices on the + // outer and N+1 vertices on + // the inner circle. the + // first N+1 ones are on the + // outer one, and all are + // numbered counter-clockwise + std::vector > vertices(2*(N+1)); + for (unsigned int i=0; i<=N; ++i) + { + // enforce that the x-coordinates + // of the first and last point of + // each half-circle are exactly + // zero (contrary to what we may + // compute using the imprecise + // value of pi) + vertices[i] = Point<2>( ( (i==0) || (i==N) ? + 0 : + std::cos(pi * i/N - pi/2) ), + std::sin(pi * i/N - pi/2)) * outer_radius; + vertices[i+N+1] = vertices[i] * (inner_radius/outer_radius); + + vertices[i] += center; + vertices[i+N+1] += center; + }; -template <> -void -GridGenerator::half_hyper_ball (Triangulation<2> &tria, - const Point<2> &p, - const double radius) -{ - // equilibrate cell sizes at - // transition from the inner part - // to the radial cells - const double a = 1./(1+std::sqrt(2.0)); - const Point<2> vertices[8] = { p+Point<2>(0,-1) *radius, - p+Point<2>(+1,-1) *(radius/std::sqrt(2.0)), - p+Point<2>(0,-1) *(radius/std::sqrt(2.0)*a), - p+Point<2>(+1,-1) *(radius/std::sqrt(2.0)*a), - p+Point<2>(0,+1) *(radius/std::sqrt(2.0)*a), - p+Point<2>(+1,+1) *(radius/std::sqrt(2.0)*a), - p+Point<2>(0,+1) *radius, - p+Point<2>(+1,+1) *(radius/std::sqrt(2.0)) - }; - - const int cell_vertices[5][4] = {{0, 1, 2, 3}, - {2, 3, 4, 5}, - {1, 7, 3, 5}, - {6, 4, 7, 5} - }; - - std::vector > cells (4, CellData<2>()); - - for (unsigned int i=0; i<4; ++i) - { - for (unsigned int j=0; j<4; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; - }; + std::vector > cells (N, CellData<2>()); - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[8]), - cells, - SubCellData()); // no boundary information + for (unsigned int i=0; i::cell_iterator cell = tria.begin(); - Triangulation<2>::cell_iterator end = tria.end(); + cells[i].material_id = 0; + }; + tria.create_triangulation (vertices, cells, SubCellData()); - while (cell != end) - { - for (unsigned int i=0; i::faces_per_cell; ++i) - { - if (cell->face(i)->boundary_indicator() == numbers::internal_face_boundary_id) - continue; + if (colorize) + { + Triangulation<2>::cell_iterator cell = tria.begin(); + for (; cell!=tria.end(); ++cell) + { + cell->face(2)->set_boundary_indicator(1); + } + tria.begin()->face(0)->set_boundary_indicator(3); - // If x is zero, then this is part of the plane - if (cell->face(i)->center()(0) < p(0)+1.e-5) - cell->face(i)->set_boundary_indicator(1); - } - ++cell; - } -} + tria.last()->face(1)->set_boundary_indicator(2); + } + } + template <> + void quarter_hyper_shell (Triangulation<2> &tria, + const Point<2> ¢er, + const double inner_radius, + const double outer_radius, + const unsigned int n_cells, + const bool colorize) + { + Assert ((inner_radius > 0) && (inner_radius < outer_radius), + ExcInvalidRadii ()); + + const double pi = numbers::PI; + // determine the number of cells + // for the grid. if not provided by + // the user determine it such that + // the length of each cell on the + // median (in the middle between + // the two circles) is equal to its + // radial extent (which is the + // difference between the two + // radii) + const unsigned int N = (n_cells == 0 ? + static_cast + (std::ceil((pi* (outer_radius + inner_radius)/4) / + (outer_radius - inner_radius))) : + n_cells); + + // set up N+1 vertices on the + // outer and N+1 vertices on + // the inner circle. the + // first N+1 ones are on the + // outer one, and all are + // numbered counter-clockwise + std::vector > vertices(2*(N+1)); + for (unsigned int i=0; i<=N; ++i) + { + // enforce that the x-coordinates + // of the last point is exactly + // zero (contrary to what we may + // compute using the imprecise + // value of pi) + vertices[i] = Point<2>( ( (i==N) ? + 0 : + std::cos(pi * i/N/2) ), + std::sin(pi * i/N/2)) * outer_radius; + vertices[i+N+1] = vertices[i] * (inner_radius/outer_radius); + + vertices[i] += center; + vertices[i+N+1] += center; + }; -// Implementation for 2D only -template <> -void -GridGenerator::half_hyper_shell (Triangulation<2> &tria, - const Point<2> ¢er, - const double inner_radius, - const double outer_radius, - const size_type n_cells, - const bool colorize) -{ - Assert ((inner_radius > 0) && (inner_radius < outer_radius), - ExcInvalidRadii ()); - - const double pi = numbers::PI; - // determine the number of cells - // for the grid. if not provided by - // the user determine it such that - // the length of each cell on the - // median (in the middle between - // the two circles) is equal to its - // radial extent (which is the - // difference between the two - // radii) - const size_type N = (n_cells == 0 ? - static_cast - (std::ceil((pi* (outer_radius + inner_radius)/2) / - (outer_radius - inner_radius))) : - n_cells); - - // set up N+1 vertices on the - // outer and N+1 vertices on - // the inner circle. the - // first N+1 ones are on the - // outer one, and all are - // numbered counter-clockwise - std::vector > vertices(2*(N+1)); - for (size_type i=0; i<=N; ++i) - { - // enforce that the x-coordinates - // of the first and last point of - // each half-circle are exactly - // zero (contrary to what we may - // compute using the imprecise - // value of pi) - vertices[i] = Point<2>( ( (i==0) || (i==N) ? - 0 : - std::cos(pi * i/N - pi/2) ), - std::sin(pi * i/N - pi/2)) * outer_radius; - vertices[i+N+1] = vertices[i] * (inner_radius/outer_radius); - - vertices[i] += center; - vertices[i+N+1] += center; - }; + std::vector > cells (N, CellData<2>()); - std::vector > cells (N, CellData<2>()); + for (unsigned int i=0; i::cell_iterator cell = tria.begin(); + for (; cell!=tria.end(); ++cell) + { + cell->face(2)->set_boundary_indicator(1); + } + tria.begin()->face(0)->set_boundary_indicator(3); - if (colorize) - { - Triangulation<2>::cell_iterator cell = tria.begin(); - for (; cell!=tria.end(); ++cell) - { - cell->face(2)->set_boundary_indicator(1); - } - tria.begin()->face(0)->set_boundary_indicator(3); + tria.last()->face(1)->set_boundary_indicator(2); + } + } - tria.last()->face(1)->set_boundary_indicator(2); - } -} -template <> -void GridGenerator::quarter_hyper_shell (Triangulation<2> &tria, - const Point<2> ¢er, - const double inner_radius, - const double outer_radius, - const size_type n_cells, - const bool colorize) -{ - Assert ((inner_radius > 0) && (inner_radius < outer_radius), - ExcInvalidRadii ()); - - const double pi = numbers::PI; - // determine the number of cells - // for the grid. if not provided by - // the user determine it such that - // the length of each cell on the - // median (in the middle between - // the two circles) is equal to its - // radial extent (which is the - // difference between the two - // radii) - const size_type N = (n_cells == 0 ? - static_cast - (std::ceil((pi* (outer_radius + inner_radius)/4) / - (outer_radius - inner_radius))) : - n_cells); - - // set up N+1 vertices on the - // outer and N+1 vertices on - // the inner circle. the - // first N+1 ones are on the - // outer one, and all are - // numbered counter-clockwise - std::vector > vertices(2*(N+1)); - for (size_type i=0; i<=N; ++i) - { - // enforce that the x-coordinates - // of the last point is exactly - // zero (contrary to what we may - // compute using the imprecise - // value of pi) - vertices[i] = Point<2>( ( (i==N) ? - 0 : - std::cos(pi * i/N/2) ), - std::sin(pi * i/N/2)) * outer_radius; - vertices[i+N+1] = vertices[i] * (inner_radius/outer_radius); - - vertices[i] += center; - vertices[i+N+1] += center; +// Implementation for 3D only + template <> + void hyper_cube_slit (Triangulation<3> &tria, + const double left, + const double right, + const bool colorize) + { + const double rl2=(right+left)/2; + const double len = (right-left)/2.; + + const Point<3> vertices[20] = + { + Point<3>(left, left , -len/2.), + Point<3>(rl2, left , -len/2.), + Point<3>(rl2, rl2 , -len/2.), + Point<3>(left, rl2 , -len/2.), + Point<3>(right,left , -len/2.), + Point<3>(right,rl2 , -len/2.), + Point<3>(rl2, right, -len/2.), + Point<3>(left, right, -len/2.), + Point<3>(right,right, -len/2.), + Point<3>(rl2, left , -len/2.), + Point<3>(left, left , len/2.), + Point<3>(rl2, left , len/2.), + Point<3>(rl2, rl2 , len/2.), + Point<3>(left, rl2 , len/2.), + Point<3>(right,left , len/2.), + Point<3>(right,rl2 , len/2.), + Point<3>(rl2, right, len/2.), + Point<3>(left, right, len/2.), + Point<3>(right,right, len/2.), + Point<3>(rl2, left , len/2.) }; - - - std::vector > cells (N, CellData<2>()); - - for (size_type i=0; i > cells (4, CellData<3>()); + for (unsigned int i=0; i<4; ++i) + { + for (unsigned int j=0; j<8; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[20]), + cells, + SubCellData()); // no boundary information - tria.create_triangulation (vertices, cells, SubCellData()); - - if (colorize) - { - Triangulation<2>::cell_iterator cell = tria.begin(); - for (; cell!=tria.end(); ++cell) - { - cell->face(2)->set_boundary_indicator(1); - } - tria.begin()->face(0)->set_boundary_indicator(3); - - tria.last()->face(1)->set_boundary_indicator(2); - } -} + if (colorize) + { + Assert(false, ExcNotImplemented()); + Triangulation<3>::cell_iterator cell = tria.begin(); + cell->face(1)->set_boundary_indicator(1); + ++cell; + cell->face(3)->set_boundary_indicator(2); + } + } // Implementation for 3D only -template <> -void GridGenerator::hyper_cube_slit (Triangulation<3> &tria, - const double left, - const double right, - const bool colorize) -{ - const double rl2=(right+left)/2; - const double len = (right-left)/2.; - - const Point<3> vertices[20] = + template <> + void enclosed_hyper_cube (Triangulation<3> &tria, + const double left, + const double right, + const double thickness, + const bool colorize) { - Point<3>(left, left , -len/2.), - Point<3>(rl2, left , -len/2.), - Point<3>(rl2, rl2 , -len/2.), - Point<3>(left, rl2 , -len/2.), - Point<3>(right,left , -len/2.), - Point<3>(right,rl2 , -len/2.), - Point<3>(rl2, right, -len/2.), - Point<3>(left, right, -len/2.), - Point<3>(right,right, -len/2.), - Point<3>(rl2, left , -len/2.), - Point<3>(left, left , len/2.), - Point<3>(rl2, left , len/2.), - Point<3>(rl2, rl2 , len/2.), - Point<3>(left, rl2 , len/2.), - Point<3>(right,left , len/2.), - Point<3>(right,rl2 , len/2.), - Point<3>(rl2, right, len/2.), - Point<3>(left, right, len/2.), - Point<3>(right,right, len/2.), - Point<3>(rl2, left , len/2.) - }; - const int cell_vertices[4][8] = { { 0,1,3,2, 10, 11, 13, 12 }, - { 9,4,2,5, 19,14, 12, 15 }, - { 3,2,7,6,13,12,17,16 }, - { 2,5,6,8,12,15,16,18 } - }; - std::vector > cells (4, CellData<3>()); - for (unsigned int i=0; i<4; ++i) - { - for (unsigned int j=0; j<8; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; + Assert(left > vertices(64); + double coords[4]; + coords[0] = left-thickness; + coords[1] = left; + coords[2] = right; + coords[3] = right+thickness; + + unsigned int k=0; + for (unsigned int z=0; z<4; ++z) + for (unsigned int y=0; y<4; ++y) + for (unsigned int x=0; x<4; ++x) + vertices[k++] = Point<3>(coords[x], coords[y], coords[z]); + + const types::material_id materials[27] = + { + 21,20,22, + 17,16,18, + 25,24,26, + 5 , 4, 6, + 1 , 0, 2, + 9 , 8,10, + 37,36,38, + 33,32,34, + 41,40,42 }; - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[20]), - cells, - SubCellData()); // no boundary information - if (colorize) - { - Assert(false, ExcNotImplemented()); - Triangulation<3>::cell_iterator cell = tria.begin(); - cell->face(1)->set_boundary_indicator(1); - ++cell; - cell->face(3)->set_boundary_indicator(2); - } -} + std::vector > cells(27); + k = 0; + for (unsigned int z=0; z<3; ++z) + for (unsigned int y=0; y<3; ++y) + for (unsigned int x=0; x<3; ++x) + { + cells[k].vertices[0] = x+4*y+16*z; + cells[k].vertices[1] = x+4*y+16*z+1; + cells[k].vertices[2] = x+4*y+16*z+4; + cells[k].vertices[3] = x+4*y+16*z+5; + cells[k].vertices[4] = x+4*y+16*z+16; + cells[k].vertices[5] = x+4*y+16*z+17; + cells[k].vertices[6] = x+4*y+16*z+20; + cells[k].vertices[7] = x+4*y+16*z+21; + if (colorize) + cells[k].material_id = materials[k]; + ++k; + } + tria.create_triangulation ( + vertices, + cells, + SubCellData()); // no boundary information + } -// Implementation for 3D only -template <> -void GridGenerator::enclosed_hyper_cube (Triangulation<3> &tria, - const double left, - const double right, - const double thickness, - const bool colorize) -{ - Assert(left > vertices(64); - double coords[4]; - coords[0] = left-thickness; - coords[1] = left; - coords[2] = right; - coords[3] = right+thickness; - - unsigned int k=0; - for (unsigned int z=0; z<4; ++z) - for (unsigned int y=0; y<4; ++y) - for (unsigned int x=0; x<4; ++x) - vertices[k++] = Point<3>(coords[x], coords[y], coords[z]); - - const types::material_id materials[27] = + template <> + void truncated_cone (Triangulation<3> &triangulation, + const double radius_0, + const double radius_1, + const double half_length) { - 21,20,22, - 17,16,18, - 25,24,26, - 5 , 4, 6, - 1 , 0, 2, - 9 , 8,10, - 37,36,38, - 33,32,34, - 41,40,42 - }; - - std::vector > cells(27); - k = 0; - for (unsigned int z=0; z<3; ++z) - for (unsigned int y=0; y<3; ++y) - for (unsigned int x=0; x<3; ++x) - { - cells[k].vertices[0] = x+4*y+16*z; - cells[k].vertices[1] = x+4*y+16*z+1; - cells[k].vertices[2] = x+4*y+16*z+4; - cells[k].vertices[3] = x+4*y+16*z+5; - cells[k].vertices[4] = x+4*y+16*z+16; - cells[k].vertices[5] = x+4*y+16*z+17; - cells[k].vertices[6] = x+4*y+16*z+20; - cells[k].vertices[7] = x+4*y+16*z+21; - if (colorize) - cells[k].material_id = materials[k]; - ++k; - } - tria.create_triangulation ( - vertices, - cells, - SubCellData()); // no boundary information -} - - - -template <> -void GridGenerator::truncated_cone (Triangulation<3> &triangulation, - const double radius_0, - const double radius_1, - const double half_length) -{ - // Determine number of cells and vertices - const size_type - n_cells = static_cast(std::floor (half_length / - std::max (radius_0, - radius_1) + - 0.5)); - const size_type n_vertices = 4 * (n_cells + 1); - std::vector > vertices_tmp(n_vertices); - - vertices_tmp[0] = Point<3> (-half_length, 0, -radius_0); - vertices_tmp[1] = Point<3> (-half_length, radius_0, 0); - vertices_tmp[2] = Point<3> (-half_length, -radius_0, 0); - vertices_tmp[3] = Point<3> (-half_length, 0, radius_0); - - const double dx = 2 * half_length / n_cells; - - for (size_type i = 0; i < n_cells; ++i) - { - vertices_tmp[4 * (i + 1)] - = vertices_tmp[4 * i] + - Point<3> (dx, 0, 0.5 * (radius_0 - radius_1) * dx / half_length); - vertices_tmp[4 * i + 5] - = vertices_tmp[4 * i + 1] + - Point<3> (dx, 0.5 * (radius_1 - radius_0) * dx / half_length, 0); - vertices_tmp[4 * i + 6] - = vertices_tmp[4 * i + 2] + - Point<3> (dx, 0.5 * (radius_0 - radius_1) * dx / half_length, 0); - vertices_tmp[4 * i + 7] - = vertices_tmp[4 * i + 3] + - Point<3> (dx, 0, 0.5 * (radius_1 - radius_0) * dx / half_length); - } + // Determine number of cells and vertices + const unsigned int + n_cells = static_cast(std::floor (half_length / + std::max (radius_0, + radius_1) + + 0.5)); + const unsigned int n_vertices = 4 * (n_cells + 1); + std::vector > vertices_tmp(n_vertices); + + vertices_tmp[0] = Point<3> (-half_length, 0, -radius_0); + vertices_tmp[1] = Point<3> (-half_length, radius_0, 0); + vertices_tmp[2] = Point<3> (-half_length, -radius_0, 0); + vertices_tmp[3] = Point<3> (-half_length, 0, radius_0); + + const double dx = 2 * half_length / n_cells; + + for (unsigned int i = 0; i < n_cells; ++i) + { + vertices_tmp[4 * (i + 1)] + = vertices_tmp[4 * i] + + Point<3> (dx, 0, 0.5 * (radius_0 - radius_1) * dx / half_length); + vertices_tmp[4 * i + 5] + = vertices_tmp[4 * i + 1] + + Point<3> (dx, 0.5 * (radius_1 - radius_0) * dx / half_length, 0); + vertices_tmp[4 * i + 6] + = vertices_tmp[4 * i + 2] + + Point<3> (dx, 0.5 * (radius_0 - radius_1) * dx / half_length, 0); + vertices_tmp[4 * i + 7] + = vertices_tmp[4 * i + 3] + + Point<3> (dx, 0, 0.5 * (radius_1 - radius_0) * dx / half_length); + } - const std::vector > vertices (vertices_tmp.begin(), - vertices_tmp.end()); - Table<2,unsigned int> cell_vertices(n_cells,GeometryInfo<3>::vertices_per_cell); + const std::vector > vertices (vertices_tmp.begin(), + vertices_tmp.end()); + Table<2,unsigned int> cell_vertices(n_cells,GeometryInfo<3>::vertices_per_cell); - for (size_type i = 0; i < n_cells; ++i) - for (unsigned int j = 0; j < GeometryInfo<3>::vertices_per_cell; ++j) - cell_vertices[i][j] = 4 * i + j; + for (unsigned int i = 0; i < n_cells; ++i) + for (unsigned int j = 0; j < GeometryInfo<3>::vertices_per_cell; ++j) + cell_vertices[i][j] = 4 * i + j; - std::vector > cells (n_cells, CellData<3> ()); + std::vector > cells (n_cells, CellData<3> ()); - for (size_type i = 0; i < n_cells; ++i) - { - for (unsigned int j = 0; j < GeometryInfo<3>::vertices_per_cell; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; + for (unsigned int i = 0; i < n_cells; ++i) + { + for (unsigned int j = 0; j < GeometryInfo<3>::vertices_per_cell; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; - } + cells[i].material_id = 0; + } - triangulation.create_triangulation (vertices, cells, SubCellData ()); + triangulation.create_triangulation (vertices, cells, SubCellData ()); - for (Triangulation<3>::cell_iterator cell = triangulation.begin (); - cell != triangulation.end (); ++cell) - { - if (cell->vertex (0) (0) == -half_length) - { - cell->face (4)->set_boundary_indicator (1); + for (Triangulation<3>::cell_iterator cell = triangulation.begin (); + cell != triangulation.end (); ++cell) + { + if (cell->vertex (0) (0) == -half_length) + { + cell->face (4)->set_boundary_indicator (1); - for (unsigned int i = 0; i < 4; ++i) - cell->line (i)->set_boundary_indicator (0); - } + for (unsigned int i = 0; i < 4; ++i) + cell->line (i)->set_boundary_indicator (0); + } - if (cell->vertex (4) (0) == half_length) - { - cell->face (5)->set_boundary_indicator (2); + if (cell->vertex (4) (0) == half_length) + { + cell->face (5)->set_boundary_indicator (2); - for (unsigned int i = 4; i < 8; ++i) - cell->line (i)->set_boundary_indicator (0); - } + for (unsigned int i = 4; i < 8; ++i) + cell->line (i)->set_boundary_indicator (0); + } - for (unsigned int i = 0; i < 4; ++i) - cell->face (i)->set_boundary_indicator (0); - } -} + for (unsigned int i = 0; i < 4; ++i) + cell->face (i)->set_boundary_indicator (0); + } + } // Implementation for 3D only -template <> -void -GridGenerator::hyper_L (Triangulation<3> &tria, - const double a, - const double b) -{ - // we slice out the top back right - // part of the cube - const Point<3> vertices[26] - = + template <> + void + hyper_L (Triangulation<3> &tria, + const double a, + const double b) { - // front face of the big cube - Point<3> (a, a,a), - Point<3> ((a+b)/2,a,a), - Point<3> (b, a,a), - Point<3> (a, a,(a+b)/2), - Point<3> ((a+b)/2,a,(a+b)/2), - Point<3> (b, a,(a+b)/2), - Point<3> (a, a,b), - Point<3> ((a+b)/2,a,b), - Point<3> (b, a,b), - // middle face of the big cube - Point<3> (a, (a+b)/2,a), - Point<3> ((a+b)/2,(a+b)/2,a), - Point<3> (b, (a+b)/2,a), - Point<3> (a, (a+b)/2,(a+b)/2), - Point<3> ((a+b)/2,(a+b)/2,(a+b)/2), - Point<3> (b, (a+b)/2,(a+b)/2), - Point<3> (a, (a+b)/2,b), - Point<3> ((a+b)/2,(a+b)/2,b), - Point<3> (b, (a+b)/2,b), - // back face of the big cube - // last (top right) point is missing - Point<3> (a, b,a), - Point<3> ((a+b)/2,b,a), - Point<3> (b, b,a), - Point<3> (a, b,(a+b)/2), - Point<3> ((a+b)/2,b,(a+b)/2), - Point<3> (b, b,(a+b)/2), - Point<3> (a, b,b), - Point<3> ((a+b)/2,b,b) - }; - const int cell_vertices[7][8] = {{0, 1, 9, 10, 3, 4, 12, 13}, - {1, 2, 10, 11, 4, 5, 13, 14}, - {3, 4, 12, 13, 6, 7, 15, 16}, - {4, 5, 13, 14, 7, 8, 16, 17}, - {9, 10, 18, 19, 12, 13, 21, 22}, - {10, 11, 19, 20, 13, 14, 22, 23}, - {12, 13, 21, 22, 15, 16, 24, 25} - }; - - std::vector > cells (7, CellData<3>()); - - for (unsigned int i=0; i<7; ++i) - { - for (unsigned int j=0; j<8; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; + // we slice out the top back right + // part of the cube + const Point<3> vertices[26] + = + { + // front face of the big cube + Point<3> (a, a,a), + Point<3> ((a+b)/2,a,a), + Point<3> (b, a,a), + Point<3> (a, a,(a+b)/2), + Point<3> ((a+b)/2,a,(a+b)/2), + Point<3> (b, a,(a+b)/2), + Point<3> (a, a,b), + Point<3> ((a+b)/2,a,b), + Point<3> (b, a,b), + // middle face of the big cube + Point<3> (a, (a+b)/2,a), + Point<3> ((a+b)/2,(a+b)/2,a), + Point<3> (b, (a+b)/2,a), + Point<3> (a, (a+b)/2,(a+b)/2), + Point<3> ((a+b)/2,(a+b)/2,(a+b)/2), + Point<3> (b, (a+b)/2,(a+b)/2), + Point<3> (a, (a+b)/2,b), + Point<3> ((a+b)/2,(a+b)/2,b), + Point<3> (b, (a+b)/2,b), + // back face of the big cube + // last (top right) point is missing + Point<3> (a, b,a), + Point<3> ((a+b)/2,b,a), + Point<3> (b, b,a), + Point<3> (a, b,(a+b)/2), + Point<3> ((a+b)/2,b,(a+b)/2), + Point<3> (b, b,(a+b)/2), + Point<3> (a, b,b), + Point<3> ((a+b)/2,b,b) + }; + const int cell_vertices[7][8] = {{0, 1, 9, 10, 3, 4, 12, 13}, + {1, 2, 10, 11, 4, 5, 13, 14}, + {3, 4, 12, 13, 6, 7, 15, 16}, + {4, 5, 13, 14, 7, 8, 16, 17}, + {9, 10, 18, 19, 12, 13, 21, 22}, + {10, 11, 19, 20, 13, 14, 22, 23}, + {12, 13, 21, 22, 15, 16, 24, 25} }; - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[26]), - cells, - SubCellData()); // no boundary information -} - - + std::vector > cells (7, CellData<3>()); -// Implementation for 3D only -template <> -void -GridGenerator::hyper_ball (Triangulation<3> &tria, - const Point<3> &p, - const double radius) -{ - const double a = 1./(1+std::sqrt(3.0)); // equilibrate cell sizes at transition - // from the inner part to the radial - // cells - const unsigned int n_vertices = 16; - const Point<3> vertices[n_vertices] - = - { - // first the vertices of the inner - // cell - p+Point<3>(-1,-1,-1) *(radius/std::sqrt(3.0)*a), - p+Point<3>(+1,-1,-1) *(radius/std::sqrt(3.0)*a), - p+Point<3>(+1,-1,+1) *(radius/std::sqrt(3.0)*a), - p+Point<3>(-1,-1,+1) *(radius/std::sqrt(3.0)*a), - p+Point<3>(-1,+1,-1) *(radius/std::sqrt(3.0)*a), - p+Point<3>(+1,+1,-1) *(radius/std::sqrt(3.0)*a), - p+Point<3>(+1,+1,+1) *(radius/std::sqrt(3.0)*a), - p+Point<3>(-1,+1,+1) *(radius/std::sqrt(3.0)*a), - // now the eight vertices at - // the outer sphere - p+Point<3>(-1,-1,-1) *(radius/std::sqrt(3.0)), - p+Point<3>(+1,-1,-1) *(radius/std::sqrt(3.0)), - p+Point<3>(+1,-1,+1) *(radius/std::sqrt(3.0)), - p+Point<3>(-1,-1,+1) *(radius/std::sqrt(3.0)), - p+Point<3>(-1,+1,-1) *(radius/std::sqrt(3.0)), - p+Point<3>(+1,+1,-1) *(radius/std::sqrt(3.0)), - p+Point<3>(+1,+1,+1) *(radius/std::sqrt(3.0)), - p+Point<3>(-1,+1,+1) *(radius/std::sqrt(3.0)), - }; - - // one needs to draw the seven cubes to - // understand what's going on here - const unsigned int n_cells = 7; - const int cell_vertices[n_cells][8] = {{0, 1, 4, 5, 3, 2, 7, 6}, // center - {8, 9, 12, 13, 0, 1, 4, 5}, // bottom - {9, 13, 1, 5, 10, 14, 2, 6}, // right - {11, 10, 3, 2, 15, 14, 7, 6}, // top - {8, 0, 12, 4, 11, 3, 15, 7}, // left - {8, 9, 0, 1, 11, 10, 3, 2}, // front - {12, 4, 13, 5, 15, 7, 14, 6} - }; // back - - std::vector > cells (n_cells, CellData<3>()); - - for (unsigned int i=0; i::vertices_per_cell; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; - }; + for (unsigned int i=0; i<7; ++i) + { + for (unsigned int j=0; j<8; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[n_vertices]), - cells, - SubCellData()); // no boundary information -} + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[26]), + cells, + SubCellData()); // no boundary information + } // Implementation for 3D only -template <> -void -GridGenerator::cylinder (Triangulation<3> &tria, - const double radius, - const double half_length) -{ - // Copy the base from hyper_ball<3> - // and transform it to yz - const double d = radius/std::sqrt(2.0); - const double a = d/(1+std::sqrt(2.0)); - Point<3> vertices[24] = - { - Point<3>(-d, -half_length,-d), - Point<3>( d, -half_length,-d), - Point<3>(-a, -half_length,-a), - Point<3>( a, -half_length,-a), - Point<3>(-a, -half_length, a), - Point<3>( a, -half_length, a), - Point<3>(-d, -half_length, d), - Point<3>( d, -half_length, d), - Point<3>(-d, 0,-d), - Point<3>( d, 0,-d), - Point<3>(-a, 0,-a), - Point<3>( a, 0,-a), - Point<3>(-a, 0, a), - Point<3>( a, 0, a), - Point<3>(-d, 0, d), - Point<3>( d, 0, d), - Point<3>(-d, half_length,-d), - Point<3>( d, half_length,-d), - Point<3>(-a, half_length,-a), - Point<3>( a, half_length,-a), - Point<3>(-a, half_length, a), - Point<3>( a, half_length, a), - Point<3>(-d, half_length, d), - Point<3>( d, half_length, d), - }; - // Turn cylinder such that y->x - for (unsigned int i=0; i<24; ++i) - { - const double h = vertices[i](1); - vertices[i](1) = -vertices[i](0); - vertices[i](0) = h; - } - - int cell_vertices[10][8] = + template <> + void + hyper_ball (Triangulation<3> &tria, + const Point<3> &p, + const double radius) { - {0, 1, 8, 9, 2, 3, 10, 11}, - {0, 2, 8, 10, 6, 4, 14, 12}, - {2, 3, 10, 11, 4, 5, 12, 13}, - {1, 7, 9, 15, 3, 5, 11, 13}, - {6, 4, 14, 12, 7, 5, 15, 13} - }; - for (unsigned int i=0; i<5; ++i) - for (unsigned int j=0; j<8; ++j) - cell_vertices[i+5][j] = cell_vertices[i][j]+8; - - std::vector > cells (10, CellData<3>()); - - for (unsigned int i=0; i<10; ++i) - { - for (unsigned int j=0; j<8; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; + const double a = 1./(1+std::sqrt(3.0)); // equilibrate cell sizes at transition + // from the inner part to the radial + // cells + const unsigned int n_vertices = 16; + const Point<3> vertices[n_vertices] + = + { + // first the vertices of the inner + // cell + p+Point<3>(-1,-1,-1) *(radius/std::sqrt(3.0)*a), + p+Point<3>(+1,-1,-1) *(radius/std::sqrt(3.0)*a), + p+Point<3>(+1,-1,+1) *(radius/std::sqrt(3.0)*a), + p+Point<3>(-1,-1,+1) *(radius/std::sqrt(3.0)*a), + p+Point<3>(-1,+1,-1) *(radius/std::sqrt(3.0)*a), + p+Point<3>(+1,+1,-1) *(radius/std::sqrt(3.0)*a), + p+Point<3>(+1,+1,+1) *(radius/std::sqrt(3.0)*a), + p+Point<3>(-1,+1,+1) *(radius/std::sqrt(3.0)*a), + // now the eight vertices at + // the outer sphere + p+Point<3>(-1,-1,-1) *(radius/std::sqrt(3.0)), + p+Point<3>(+1,-1,-1) *(radius/std::sqrt(3.0)), + p+Point<3>(+1,-1,+1) *(radius/std::sqrt(3.0)), + p+Point<3>(-1,-1,+1) *(radius/std::sqrt(3.0)), + p+Point<3>(-1,+1,-1) *(radius/std::sqrt(3.0)), + p+Point<3>(+1,+1,-1) *(radius/std::sqrt(3.0)), + p+Point<3>(+1,+1,+1) *(radius/std::sqrt(3.0)), + p+Point<3>(-1,+1,+1) *(radius/std::sqrt(3.0)), }; - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[24]), - cells, - SubCellData()); // no boundary information - - // set boundary indicators for the - // faces at the ends to 1 and 2, - // respectively. note that we also - // have to deal with those lines - // that are purely in the interior - // of the ends. we determine whether - // an edge is purely in the - // interior if one of its vertices - // is at coordinates '+-a' as set - // above - Triangulation<3>::cell_iterator cell = tria.begin(); - Triangulation<3>::cell_iterator end = tria.end(); - - for (; cell != end; ++cell) - for (unsigned int i=0; i::faces_per_cell; ++i) - if (cell->at_boundary(i)) - { - if (cell->face(i)->center()(0) > half_length-1.e-5) - { - cell->face(i)->set_boundary_indicator(2); - - for (unsigned int e=0; e::lines_per_face; ++e) - if ((std::fabs(cell->face(i)->line(e)->vertex(0)[1]) == a) || - (std::fabs(cell->face(i)->line(e)->vertex(0)[2]) == a) || - (std::fabs(cell->face(i)->line(e)->vertex(1)[1]) == a) || - (std::fabs(cell->face(i)->line(e)->vertex(1)[2]) == a)) - cell->face(i)->line(e)->set_boundary_indicator(2); - } - else if (cell->face(i)->center()(0) < -half_length+1.e-5) - { - cell->face(i)->set_boundary_indicator(1); + // one needs to draw the seven cubes to + // understand what's going on here + const unsigned int n_cells = 7; + const int cell_vertices[n_cells][8] = {{0, 1, 4, 5, 3, 2, 7, 6}, // center + {8, 9, 12, 13, 0, 1, 4, 5}, // bottom + {9, 13, 1, 5, 10, 14, 2, 6}, // right + {11, 10, 3, 2, 15, 14, 7, 6}, // top + {8, 0, 12, 4, 11, 3, 15, 7}, // left + {8, 9, 0, 1, 11, 10, 3, 2}, // front + {12, 4, 13, 5, 15, 7, 14, 6} + }; // back + + std::vector > cells (n_cells, CellData<3>()); + + for (unsigned int i=0; i::vertices_per_cell; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; - for (unsigned int e=0; e::lines_per_face; ++e) - if ((std::fabs(cell->face(i)->line(e)->vertex(0)[1]) == a) || - (std::fabs(cell->face(i)->line(e)->vertex(0)[2]) == a) || - (std::fabs(cell->face(i)->line(e)->vertex(1)[1]) == a) || - (std::fabs(cell->face(i)->line(e)->vertex(1)[2]) == a)) - cell->face(i)->line(e)->set_boundary_indicator(1); - } - } -} + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[n_vertices]), + cells, + SubCellData()); // no boundary information + } // Implementation for 3D only -template <> -void -GridGenerator::half_hyper_ball (Triangulation<3> &tria, - const Point<3> ¢er, - const double radius) -{ - // These are for the two lower squares - const double d = radius/std::sqrt(2.0); - const double a = d/(1+std::sqrt(2.0)); - // These are for the two upper square - const double b = a/2.0; - const double c = d/2.0; - // And so are these - const double hb = radius*std::sqrt(3.0)/4.0; - const double hc = radius*std::sqrt(3.0)/2.0; - - Point<3> vertices[16] = + template <> + void + cylinder (Triangulation<3> &tria, + const double radius, + const double half_length) { - center+Point<3>( 0, d, -d), - center+Point<3>( 0, -d, -d), - center+Point<3>( 0, a, -a), - center+Point<3>( 0, -a, -a), - center+Point<3>( 0, a, a), - center+Point<3>( 0, -a, a), - center+Point<3>( 0, d, d), - center+Point<3>( 0, -d, d), - - center+Point<3>(hc, c, -c), - center+Point<3>(hc, -c, -c), - center+Point<3>(hb, b, -b), - center+Point<3>(hb, -b, -b), - center+Point<3>(hb, b, b), - center+Point<3>(hb, -b, b), - center+Point<3>(hc, c, c), - center+Point<3>(hc, -c, c), - }; - - int cell_vertices[6][8] = - { - {0, 1, 8, 9, 2, 3, 10, 11}, - {0, 2, 8, 10, 6, 4, 14, 12}, - {2, 3, 10, 11, 4, 5, 12, 13}, - {1, 7, 9, 15, 3, 5, 11, 13}, - {6, 4, 14, 12, 7, 5, 15, 13}, - {8, 10, 9, 11, 14, 12, 15, 13} - }; - - std::vector > cells (6, CellData<3>()); + // Copy the base from hyper_ball<3> + // and transform it to yz + const double d = radius/std::sqrt(2.0); + const double a = d/(1+std::sqrt(2.0)); + Point<3> vertices[24] = + { + Point<3>(-d, -half_length,-d), + Point<3>( d, -half_length,-d), + Point<3>(-a, -half_length,-a), + Point<3>( a, -half_length,-a), + Point<3>(-a, -half_length, a), + Point<3>( a, -half_length, a), + Point<3>(-d, -half_length, d), + Point<3>( d, -half_length, d), + Point<3>(-d, 0,-d), + Point<3>( d, 0,-d), + Point<3>(-a, 0,-a), + Point<3>( a, 0,-a), + Point<3>(-a, 0, a), + Point<3>( a, 0, a), + Point<3>(-d, 0, d), + Point<3>( d, 0, d), + Point<3>(-d, half_length,-d), + Point<3>( d, half_length,-d), + Point<3>(-a, half_length,-a), + Point<3>( a, half_length,-a), + Point<3>(-a, half_length, a), + Point<3>( a, half_length, a), + Point<3>(-d, half_length, d), + Point<3>( d, half_length, d), + }; + // Turn cylinder such that y->x + for (unsigned int i=0; i<24; ++i) + { + const double h = vertices[i](1); + vertices[i](1) = -vertices[i](0); + vertices[i](0) = h; + } - for (unsigned int i=0; i<6; ++i) + int cell_vertices[10][8] = { - for (unsigned int j=0; j<8; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; + {0, 1, 8, 9, 2, 3, 10, 11}, + {0, 2, 8, 10, 6, 4, 14, 12}, + {2, 3, 10, 11, 4, 5, 12, 13}, + {1, 7, 9, 15, 3, 5, 11, 13}, + {6, 4, 14, 12, 7, 5, 15, 13} }; + for (unsigned int i=0; i<5; ++i) + for (unsigned int j=0; j<8; ++j) + cell_vertices[i+5][j] = cell_vertices[i][j]+8; - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[16]), - cells, - SubCellData()); // no boundary information + std::vector > cells (10, CellData<3>()); - Triangulation<3>::cell_iterator cell = tria.begin(); - Triangulation<3>::cell_iterator end = tria.end(); + for (unsigned int i=0; i<10; ++i) + { + for (unsigned int j=0; j<8; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; - // go over all faces. for the ones on the flat face, set boundary - // indicator for face and edges to one; the rest will remain at - // zero but we have to pay attention to those edges that are - // at the perimeter of the flat face since they should not be - // set to one - while (cell != end) - { + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[24]), + cells, + SubCellData()); // no boundary information + + // set boundary indicators for the + // faces at the ends to 1 and 2, + // respectively. note that we also + // have to deal with those lines + // that are purely in the interior + // of the ends. we determine whether + // an edge is purely in the + // interior if one of its vertices + // is at coordinates '+-a' as set + // above + Triangulation<3>::cell_iterator cell = tria.begin(); + Triangulation<3>::cell_iterator end = tria.end(); + + for (; cell != end; ++cell) for (unsigned int i=0; i::faces_per_cell; ++i) - { - if (!cell->at_boundary(i)) - continue; + if (cell->at_boundary(i)) + { + if (cell->face(i)->center()(0) > half_length-1.e-5) + { + cell->face(i)->set_boundary_indicator(2); + + for (unsigned int e=0; e::lines_per_face; ++e) + if ((std::fabs(cell->face(i)->line(e)->vertex(0)[1]) == a) || + (std::fabs(cell->face(i)->line(e)->vertex(0)[2]) == a) || + (std::fabs(cell->face(i)->line(e)->vertex(1)[1]) == a) || + (std::fabs(cell->face(i)->line(e)->vertex(1)[2]) == a)) + cell->face(i)->line(e)->set_boundary_indicator(2); + } + else if (cell->face(i)->center()(0) < -half_length+1.e-5) + { + cell->face(i)->set_boundary_indicator(1); + + for (unsigned int e=0; e::lines_per_face; ++e) + if ((std::fabs(cell->face(i)->line(e)->vertex(0)[1]) == a) || + (std::fabs(cell->face(i)->line(e)->vertex(0)[2]) == a) || + (std::fabs(cell->face(i)->line(e)->vertex(1)[1]) == a) || + (std::fabs(cell->face(i)->line(e)->vertex(1)[2]) == a)) + cell->face(i)->line(e)->set_boundary_indicator(1); + } + } + } + - // If the center is on the plane x=0, this is a planar element. set - // its boundary indicator. also set the boundary indicators of the - // bounding faces unless both vertices are on the perimeter - if (cell->face(i)->center()(0) < center(0)+1.e-5*radius) - { - cell->face(i)->set_boundary_indicator(1); - for (unsigned int j=0; j::lines_per_face; ++j) - { - const Point<3> vertices[2] - = { cell->face(i)->line(j)->vertex(0), - cell->face(i)->line(j)->vertex(1) - }; - if ((std::fabs(vertices[0].distance(center)-radius) > - 1e-5*radius) - || - (std::fabs(vertices[1].distance(center)-radius) > - 1e-5*radius)) - cell->face(i)->line(j)->set_boundary_indicator(1); - } - } - } - ++cell; - } -} // Implementation for 3D only -template<> -void -GridGenerator:: -colorize_hyper_shell (Triangulation<3> &tria, - const Point<3> &, - const double, - const double) -{ - // the following uses a good amount - // of knowledge about the - // orientation of cells. this is - // probably not good style... - if (tria.n_cells() == 6) + template <> + void + half_hyper_ball (Triangulation<3> &tria, + const Point<3> ¢er, + const double radius) + { + // These are for the two lower squares + const double d = radius/std::sqrt(2.0); + const double a = d/(1+std::sqrt(2.0)); + // These are for the two upper square + const double b = a/2.0; + const double c = d/2.0; + // And so are these + const double hb = radius*std::sqrt(3.0)/4.0; + const double hc = radius*std::sqrt(3.0)/2.0; + + Point<3> vertices[16] = + { + center+Point<3>( 0, d, -d), + center+Point<3>( 0, -d, -d), + center+Point<3>( 0, a, -a), + center+Point<3>( 0, -a, -a), + center+Point<3>( 0, a, a), + center+Point<3>( 0, -a, a), + center+Point<3>( 0, d, d), + center+Point<3>( 0, -d, d), + + center+Point<3>(hc, c, -c), + center+Point<3>(hc, -c, -c), + center+Point<3>(hb, b, -b), + center+Point<3>(hb, -b, -b), + center+Point<3>(hb, b, b), + center+Point<3>(hb, -b, b), + center+Point<3>(hc, c, c), + center+Point<3>(hc, -c, c), + }; + + int cell_vertices[6][8] = { - Triangulation<3>::cell_iterator cell = tria.begin(); + {0, 1, 8, 9, 2, 3, 10, 11}, + {0, 2, 8, 10, 6, 4, 14, 12}, + {2, 3, 10, 11, 4, 5, 12, 13}, + {1, 7, 9, 15, 3, 5, 11, 13}, + {6, 4, 14, 12, 7, 5, 15, 13}, + {8, 10, 9, 11, 14, 12, 15, 13} + }; - cell->face(4)->set_boundary_indicator(1); - Assert (cell->face(4)->at_boundary(), ExcInternalError()); + std::vector > cells (6, CellData<3>()); - (++cell)->face(2)->set_boundary_indicator(1); - Assert (cell->face(2)->at_boundary(), ExcInternalError()); + for (unsigned int i=0; i<6; ++i) + { + for (unsigned int j=0; j<8; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; - (++cell)->face(2)->set_boundary_indicator(1); - Assert (cell->face(2)->at_boundary(), ExcInternalError()); + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[16]), + cells, + SubCellData()); // no boundary information - (++cell)->face(0)->set_boundary_indicator(1); - Assert (cell->face(0)->at_boundary(), ExcInternalError()); + Triangulation<3>::cell_iterator cell = tria.begin(); + Triangulation<3>::cell_iterator end = tria.end(); - (++cell)->face(2)->set_boundary_indicator(1); - Assert (cell->face(2)->at_boundary(), ExcInternalError()); - - (++cell)->face(0)->set_boundary_indicator(1); - Assert (cell->face(0)->at_boundary(), ExcInternalError()); - } - else if (tria.n_cells() == 12) - { - // again use some internal - // knowledge - for (Triangulation<3>::cell_iterator cell = tria.begin(); - cell != tria.end(); ++cell) - { - Assert (cell->face(5)->at_boundary(), ExcInternalError()); - cell->face(5)->set_boundary_indicator(1); - } - } - else if (tria.n_cells() == 96) - { - // the 96-cell hypershell is - // based on a once refined - // 12-cell mesh. consequently, - // since the outer faces all - // are face_no==5 above, so - // they are here (unless they - // are in the interior). Use - // this to assign boundary - // indicators, but also make - // sure that we encounter - // exactly 48 such faces - unsigned int count = 0; - for (Triangulation<3>::cell_iterator cell = tria.begin(); - cell != tria.end(); ++cell) - if (cell->face(5)->at_boundary()) + // go over all faces. for the ones on the flat face, set boundary + // indicator for face and edges to one; the rest will remain at + // zero but we have to pay attention to those edges that are + // at the perimeter of the flat face since they should not be + // set to one + while (cell != end) + { + for (unsigned int i=0; i::faces_per_cell; ++i) { - cell->face(5)->set_boundary_indicator(1); - ++count; - } - Assert (count == 48, ExcInternalError()); - } - else - Assert (false, ExcNotImplemented()); -} - + if (!cell->at_boundary(i)) + continue; + // If the center is on the plane x=0, this is a planar element. set + // its boundary indicator. also set the boundary indicators of the + // bounding faces unless both vertices are on the perimeter + if (cell->face(i)->center()(0) < center(0)+1.e-5*radius) + { + cell->face(i)->set_boundary_indicator(1); + for (unsigned int j=0; j::lines_per_face; ++j) + { + const Point<3> vertices[2] + = { cell->face(i)->line(j)->vertex(0), + cell->face(i)->line(j)->vertex(1) + }; + if ((std::fabs(vertices[0].distance(center)-radius) > + 1e-5*radius) + || + (std::fabs(vertices[1].distance(center)-radius) > + 1e-5*radius)) + cell->face(i)->line(j)->set_boundary_indicator(1); + } + } + } + ++cell; + } + } -template <> -void -GridGenerator::hyper_shell (Triangulation<3> &tria, - const Point<3> &p, - const double inner_radius, - const double outer_radius, - const size_type n, - const bool colorize) -{ - Assert ((inner_radius > 0) && (inner_radius < outer_radius), - ExcInvalidRadii ()); - const double irad = inner_radius/std::sqrt(3.0); - const double orad = outer_radius/std::sqrt(3.0); - std::vector > vertices; - std::vector > cells; + template <> + void + hyper_shell (Triangulation<3> &tria, + const Point<3> &p, + const double inner_radius, + const double outer_radius, + const unsigned int n, + const bool colorize) + { + Assert ((inner_radius > 0) && (inner_radius < outer_radius), + ExcInvalidRadii ()); - // Start with the shell bounded by - // two nested cubes - if (n == 6) - { - for (unsigned int i=0; i<8; ++i) - vertices.push_back(p+hexahedron[i]*irad); - for (unsigned int i=0; i<8; ++i) - vertices.push_back(p+hexahedron[i]*orad); + const double irad = inner_radius/std::sqrt(3.0); + const double orad = outer_radius/std::sqrt(3.0); + std::vector > vertices; + std::vector > cells; - const unsigned int n_cells = 6; - const int cell_vertices[n_cells][8] = + // Start with the shell bounded by + // two nested cubes + if (n == 6) { - {8, 9, 10, 11, 0, 1, 2, 3}, // bottom - {9, 11, 1, 3, 13, 15, 5, 7}, // right - {12, 13, 4, 5, 14, 15, 6, 7}, // top - {8, 0, 10, 2, 12, 4, 14, 6}, // left - {8, 9, 0, 1, 12, 13, 4, 5}, // front - {10, 2, 11, 3, 14, 6, 15, 7} - }; // back + for (unsigned int i=0; i<8; ++i) + vertices.push_back(p+hexahedron[i]*irad); + for (unsigned int i=0; i<8; ++i) + vertices.push_back(p+hexahedron[i]*orad); - cells.resize(n_cells, CellData<3>()); - - for (unsigned int i=0; i::vertices_per_cell; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; - } + {8, 9, 10, 11, 0, 1, 2, 3}, // bottom + {9, 11, 1, 3, 13, 15, 5, 7}, // right + {12, 13, 4, 5, 14, 15, 6, 7}, // top + {8, 0, 10, 2, 12, 4, 14, 6}, // left + {8, 9, 0, 1, 12, 13, 4, 5}, // front + {10, 2, 11, 3, 14, 6, 15, 7} + }; // back - tria.create_triangulation (vertices, cells, SubCellData()); - } - // A more regular subdivision can - // be obtained by two nested - // rhombic dodecahedra - else if (n == 12) - { - for (unsigned int i=0; i<8; ++i) - vertices.push_back(p+hexahedron[i]*irad); - for (unsigned int i=0; i<6; ++i) - vertices.push_back(p+octahedron[i]*inner_radius); - for (unsigned int i=0; i<8; ++i) - vertices.push_back(p+hexahedron[i]*orad); - for (unsigned int i=0; i<6; ++i) - vertices.push_back(p+octahedron[i]*outer_radius); - - const unsigned int n_cells = 12; - const unsigned int rhombi[n_cells][4] = - { - { 10, 4, 0, 8}, - { 4, 13, 8, 6}, - { 10, 5, 4, 13}, - { 1, 9, 10, 5}, - { 9, 7, 5, 13}, - { 7, 11, 13, 6}, - { 9, 3, 7, 11}, - { 1, 12, 9, 3}, - { 12, 2, 3, 11}, - { 2, 8, 11, 6}, - { 12, 0, 2, 8}, - { 1, 10, 12, 0} - }; + cells.resize(n_cells, CellData<3>()); - cells.resize(n_cells, CellData<3>()); + for (unsigned int i=0; i::vertices_per_cell; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + } - for (unsigned int i=0; i boundary (p); - Triangulation<3> tmp; - GridGenerator::hyper_shell (tmp, p, inner_radius, outer_radius, 12); - tmp.set_boundary(0, boundary); - tmp.set_boundary(1, boundary); - tmp.refine_global (1); - - // let's determine the distance at - // which the interior nodes should be - // from the center. let's say we - // measure distances in multiples of - // outer_radius and call - // r=inner_radius. - // - // then note - // that we now have 48 faces on the - // inner and 48 on the outer sphere, - // each with an area of approximately - // 4*pi/48*r^2 and 4*pi/48, for - // a face edge length of approximately - // sqrt(pi/12)*r and sqrt(pi/12) - // - // let's say we put the interior nodes - // at a distance rho, then a measure of - // deformation for the inner cells - // would be - // di=max(sqrt(pi/12)*r/(rho-r), - // (rho-r)/sqrt(pi/12)/r) - // and for the outer cells - // do=max(sqrt(pi/12)/(1-rho), - // (1-rho)/sqrt(pi/12)) - // - // we now seek a rho so that the - // deformation of cells on the inside - // and outside is equal. there are in - // principle four possibilities for one - // of the branches of do== one of the - // branches of di, though not all of - // them satisfy do==di, of - // course. however, we are not - // interested in cases where the inner - // cell is long and skinny and the - // outer one tall -- yes, they have the - // same aspect ratio, but in different - // space directions. - // - // so it only boils down to the - // following two possibilities: the - // first branch of each max(.,.) - // functions are equal, or the second - // one are. on the other hand, since - // they two branches are reciprocals of - // each other, if one pair of branches - // is equal, so is the other - // - // this yields the following equation - // for rho: - // sqrt(pi/12)*r/(rho-r) - // == sqrt(pi/12)/(1-rho) - // with solution rho=2r/(1+r) - const double r = inner_radius / outer_radius; - const double rho = 2*r/(1+r); - - // then this is the distance of the - // interior nodes from the center: - const double middle_radius = rho * outer_radius; - - // mark vertices we've already moved or - // that we want to ignore: we don't - // want to move vertices at the inner - // or outer boundaries - std::vector vertex_already_treated (tmp.n_vertices(), false); - for (Triangulation<3>::active_cell_iterator cell = tmp.begin_active(); - cell != tmp.end(); ++cell) - for (unsigned int f=0; f::faces_per_cell; ++f) - if (cell->at_boundary(f)) - for (unsigned int v=0; v::vertices_per_face; ++v) - vertex_already_treated[cell->face(f)->vertex_index(v)] = true; - - // now move the remaining vertices - for (Triangulation<3>::active_cell_iterator cell = tmp.begin_active(); - cell != tmp.end(); ++cell) - for (unsigned int v=0; v::vertices_per_cell; ++v) - if (vertex_already_treated[cell->vertex_index(v)] == false) - { - // this is a new interior - // vertex. mesh refinement may - // have placed it at a number - // of places in radial - // direction and oftentimes not - // in a particularly good - // one. move it to halfway - // between inner and outer - // sphere - const Point<3> old_distance = cell->vertex(v) - p; - const double old_radius = cell->vertex(v).distance(p); - cell->vertex(v) = p + old_distance * (middle_radius / old_radius); - - vertex_already_treated[cell->vertex_index(v)] = true; - } + cells.resize(n_cells, CellData<3>()); - // now copy the resulting level 1 cells - // into the new triangulation, - cells.resize(tmp.n_active_cells(), CellData<3>()); + for (unsigned int i=0; i::active_cell_iterator cell = tmp.begin_active(); - cell != tmp.end(); ++cell, ++index) - { + tria.create_triangulation (vertices, cells, SubCellData()); + } + else if (n == 96) + { + // create a triangulation based on the + // 12-cell one where we refine the mesh + // once and then re-arrange all + // interior nodes so that the mesh is + // the least distorted + HyperShellBoundary<3> boundary (p); + Triangulation<3> tmp; + hyper_shell (tmp, p, inner_radius, outer_radius, 12); + tmp.set_boundary(0, boundary); + tmp.set_boundary(1, boundary); + tmp.refine_global (1); + + // let's determine the distance at + // which the interior nodes should be + // from the center. let's say we + // measure distances in multiples of + // outer_radius and call + // r=inner_radius. + // + // then note + // that we now have 48 faces on the + // inner and 48 on the outer sphere, + // each with an area of approximately + // 4*pi/48*r^2 and 4*pi/48, for + // a face edge length of approximately + // sqrt(pi/12)*r and sqrt(pi/12) + // + // let's say we put the interior nodes + // at a distance rho, then a measure of + // deformation for the inner cells + // would be + // di=max(sqrt(pi/12)*r/(rho-r), + // (rho-r)/sqrt(pi/12)/r) + // and for the outer cells + // do=max(sqrt(pi/12)/(1-rho), + // (1-rho)/sqrt(pi/12)) + // + // we now seek a rho so that the + // deformation of cells on the inside + // and outside is equal. there are in + // principle four possibilities for one + // of the branches of do== one of the + // branches of di, though not all of + // them satisfy do==di, of + // course. however, we are not + // interested in cases where the inner + // cell is long and skinny and the + // outer one tall -- yes, they have the + // same aspect ratio, but in different + // space directions. + // + // so it only boils down to the + // following two possibilities: the + // first branch of each max(.,.) + // functions are equal, or the second + // one are. on the other hand, since + // they two branches are reciprocals of + // each other, if one pair of branches + // is equal, so is the other + // + // this yields the following equation + // for rho: + // sqrt(pi/12)*r/(rho-r) + // == sqrt(pi/12)/(1-rho) + // with solution rho=2r/(1+r) + const double r = inner_radius / outer_radius; + const double rho = 2*r/(1+r); + + // then this is the distance of the + // interior nodes from the center: + const double middle_radius = rho * outer_radius; + + // mark vertices we've already moved or + // that we want to ignore: we don't + // want to move vertices at the inner + // or outer boundaries + std::vector vertex_already_treated (tmp.n_vertices(), false); + for (Triangulation<3>::active_cell_iterator cell = tmp.begin_active(); + cell != tmp.end(); ++cell) + for (unsigned int f=0; f::faces_per_cell; ++f) + if (cell->at_boundary(f)) + for (unsigned int v=0; v::vertices_per_face; ++v) + vertex_already_treated[cell->face(f)->vertex_index(v)] = true; + + // now move the remaining vertices + for (Triangulation<3>::active_cell_iterator cell = tmp.begin_active(); + cell != tmp.end(); ++cell) for (unsigned int v=0; v::vertices_per_cell; ++v) - cells[index].vertices[v] = cell->vertex_index(v); - cells[index].material_id = 0; - } - - tria.create_triangulation (tmp.get_vertices(), cells, SubCellData()); - } - else - { - Assert(false, ExcMessage ("Invalid number of coarse mesh cells.")); - } + if (vertex_already_treated[cell->vertex_index(v)] == false) + { + // this is a new interior + // vertex. mesh refinement may + // have placed it at a number + // of places in radial + // direction and oftentimes not + // in a particularly good + // one. move it to halfway + // between inner and outer + // sphere + const Point<3> old_distance = cell->vertex(v) - p; + const double old_radius = cell->vertex(v).distance(p); + cell->vertex(v) = p + old_distance * (middle_radius / old_radius); + + vertex_already_treated[cell->vertex_index(v)] = true; + } - if (colorize) - colorize_hyper_shell(tria, p, inner_radius, outer_radius); -} + // now copy the resulting level 1 cells + // into the new triangulation, + cells.resize(tmp.n_active_cells(), CellData<3>()); + unsigned int index = 0; + for (Triangulation<3>::active_cell_iterator cell = tmp.begin_active(); + cell != tmp.end(); ++cell, ++index) + { + for (unsigned int v=0; v::vertices_per_cell; ++v) + cells[index].vertices[v] = cell->vertex_index(v); + cells[index].material_id = 0; + } + tria.create_triangulation (tmp.get_vertices(), cells, SubCellData()); + } + else + { + Assert(false, ExcMessage ("Invalid number of coarse mesh cells.")); + } + if (colorize) + colorize_hyper_shell(tria, p, inner_radius, outer_radius); + } -// Implementation for 3D only -template <> -void -GridGenerator::half_hyper_shell (Triangulation<3> &tria, - const Point<3> ¢er, - const double inner_radius, - const double outer_radius, - const size_type n, - const bool colorize) -{ - Assert ((inner_radius > 0) && (inner_radius < outer_radius), - ExcInvalidRadii ()); - Assert(colorize == false, ExcNotImplemented()); - if (n <= 5) - { - // These are for the two lower squares - const double d = outer_radius/std::sqrt(2.0); - const double a = inner_radius/std::sqrt(2.0); - // These are for the two upper square - const double b = a/2.0; - const double c = d/2.0; - // And so are these - const double hb = inner_radius*std::sqrt(3.0)/2.0; - const double hc = outer_radius*std::sqrt(3.0)/2.0; - - Point<3> vertices[16] = - { - center+Point<3>( 0, d, -d), - center+Point<3>( 0, -d, -d), - center+Point<3>( 0, a, -a), - center+Point<3>( 0, -a, -a), - center+Point<3>( 0, a, a), - center+Point<3>( 0, -a, a), - center+Point<3>( 0, d, d), - center+Point<3>( 0, -d, d), - - center+Point<3>(hc, c, -c), - center+Point<3>(hc, -c, -c), - center+Point<3>(hb, b, -b), - center+Point<3>(hb, -b, -b), - center+Point<3>(hb, b, b), - center+Point<3>(hb, -b, b), - center+Point<3>(hc, c, c), - center+Point<3>(hc, -c, c), - }; - int cell_vertices[5][8] = - { - {0, 1, 8, 9, 2, 3, 10, 11}, - {0, 2, 8, 10, 6, 4, 14, 12}, - {1, 7, 9, 15, 3, 5, 11, 13}, - {6, 4, 14, 12, 7, 5, 15, 13}, - {8, 10, 9, 11, 14, 12, 15, 13} - }; - std::vector > cells (5, CellData<3>()); +// Implementation for 3D only + template <> + void + half_hyper_shell (Triangulation<3> &tria, + const Point<3> ¢er, + const double inner_radius, + const double outer_radius, + const unsigned int n, + const bool colorize) + { + Assert ((inner_radius > 0) && (inner_radius < outer_radius), + ExcInvalidRadii ()); + Assert(colorize == false, ExcNotImplemented()); - for (unsigned int i=0; i<5; ++i) + if (n <= 5) + { + // These are for the two lower squares + const double d = outer_radius/std::sqrt(2.0); + const double a = inner_radius/std::sqrt(2.0); + // These are for the two upper square + const double b = a/2.0; + const double c = d/2.0; + // And so are these + const double hb = inner_radius*std::sqrt(3.0)/2.0; + const double hc = outer_radius*std::sqrt(3.0)/2.0; + + Point<3> vertices[16] = { - for (unsigned int j=0; j<8; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; + center+Point<3>( 0, d, -d), + center+Point<3>( 0, -d, -d), + center+Point<3>( 0, a, -a), + center+Point<3>( 0, -a, -a), + center+Point<3>( 0, a, a), + center+Point<3>( 0, -a, a), + center+Point<3>( 0, d, d), + center+Point<3>( 0, -d, d), + + center+Point<3>(hc, c, -c), + center+Point<3>(hc, -c, -c), + center+Point<3>(hb, b, -b), + center+Point<3>(hb, -b, -b), + center+Point<3>(hb, b, b), + center+Point<3>(hb, -b, b), + center+Point<3>(hc, c, c), + center+Point<3>(hc, -c, c), }; - tria.create_triangulation ( - std::vector >(&vertices[0], &vertices[16]), - cells, - SubCellData()); // no boundary information - } - else - { - Assert(false, ExcIndexRange(n, 0, 5)); - } + int cell_vertices[5][8] = + { + {0, 1, 8, 9, 2, 3, 10, 11}, + {0, 2, 8, 10, 6, 4, 14, 12}, + {1, 7, 9, 15, 3, 5, 11, 13}, + {6, 4, 14, 12, 7, 5, 15, 13}, + {8, 10, 9, 11, 14, 12, 15, 13} + }; -} + std::vector > cells (5, CellData<3>()); -// Implementation for 3D only -template <> -void -GridGenerator::colorize_quarter_hyper_shell(Triangulation<3> &tria, - const Point<3> ¢er, - const double inner_radius, - const double outer_radius) -{ + for (unsigned int i=0; i<5; ++i) + { + for (unsigned int j=0; j<8; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; + }; + + tria.create_triangulation ( + std::vector >(&vertices[0], &vertices[16]), + cells, + SubCellData()); // no boundary information + } + else + { + Assert(false, ExcIndexRange(n, 0, 5)); + } - if (tria.n_cells() != 3) - AssertThrow (false, ExcNotImplemented()); + } - double middle = (outer_radius-inner_radius)/2e0 + inner_radius; - double eps = 1e-3*middle; - Triangulation<3>::cell_iterator cell = tria.begin(); - for (; cell!=tria.end(); ++cell) - for (unsigned int f=0; f::faces_per_cell; ++f) +// Implementation for 3D only + template <> + void quarter_hyper_shell (Triangulation<3> &tria, + const Point<3> ¢er, + const double inner_radius, + const double outer_radius, + const unsigned int n, + const bool colorize) + { + Assert ((inner_radius > 0) && (inner_radius < outer_radius), + ExcInvalidRadii ()); + if (n == 0 || n == 3) { - if (!cell->face(f)->at_boundary()) - continue; + const double a = inner_radius*std::sqrt(2.0)/2e0; + const double b = outer_radius*std::sqrt(2.0)/2e0; + const double c = a*std::sqrt(3.0)/2e0; + const double d = b*std::sqrt(3.0)/2e0; + const double e = outer_radius/2e0; + const double h = inner_radius/2e0; + + std::vector > vertices; + + vertices.push_back (center+Point<3>( 0, inner_radius, 0)); //0 + vertices.push_back (center+Point<3>( a, a, 0)); //1 + vertices.push_back (center+Point<3>( b, b, 0)); //2 + vertices.push_back (center+Point<3>( 0, outer_radius, 0)); //3 + vertices.push_back (center+Point<3>( 0, a , a)); //4 + vertices.push_back (center+Point<3>( c, c , h)); //5 + vertices.push_back (center+Point<3>( d, d , e)); //6 + vertices.push_back (center+Point<3>( 0, b , b)); //7 + vertices.push_back (center+Point<3>( inner_radius, 0 , 0)); //8 + vertices.push_back (center+Point<3>( outer_radius, 0 , 0)); //9 + vertices.push_back (center+Point<3>( a, 0 , a)); //10 + vertices.push_back (center+Point<3>( b, 0 , b)); //11 + vertices.push_back (center+Point<3>( 0, 0 , inner_radius)); //12 + vertices.push_back (center+Point<3>( 0, 0 , outer_radius)); //13 + + const int cell_vertices[3][8] = + { + {0, 1, 3, 2, 4, 5, 7, 6}, + {1, 8, 2, 9, 5, 10, 6, 11}, + {4, 5, 7, 6, 12, 10, 13, 11}, + }; + std::vector > cells(3); - double radius = cell->face(f)->center().norm() - center.norm(); - if (std::fabs(cell->face(f)->center()(0)) < eps ) // x = 0 set boundary 2 - { - cell->face(f)->set_boundary_indicator(2); - for (unsigned int j=0; j::lines_per_face; ++j) - if (cell->face(f)->line(j)->at_boundary()) - if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) > eps) - cell->face(f)->line(j)->set_boundary_indicator(2); - } - else if (std::fabs(cell->face(f)->center()(1)) < eps) // y = 0 set boundary 3 - { - cell->face(f)->set_boundary_indicator(3); - for (unsigned int j=0; j::lines_per_face; ++j) - if (cell->face(f)->line(j)->at_boundary()) - if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) > eps) - cell->face(f)->line(j)->set_boundary_indicator(3); - } - else if (std::fabs(cell->face(f)->center()(2)) < eps ) // z = 0 set boundary 4 - { - cell->face(f)->set_boundary_indicator(4); - for (unsigned int j=0; j::lines_per_face; ++j) - if (cell->face(f)->line(j)->at_boundary()) - if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) > eps) - cell->face(f)->line(j)->set_boundary_indicator(4); - } - else if (radius < middle) // inner radius set boundary 0 - { - cell->face(f)->set_boundary_indicator(0); - for (unsigned int j=0; j::lines_per_face; ++j) - if (cell->face(f)->line(j)->at_boundary()) - if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) < eps) - cell->face(f)->line(j)->set_boundary_indicator(0); - } - else if (radius > middle) // outer radius set boundary 1 + for (unsigned int i=0; i<3; ++i) { - cell->face(f)->set_boundary_indicator(1); - for (unsigned int j=0; j::lines_per_face; ++j) - if (cell->face(f)->line(j)->at_boundary()) - if (std::fabs(cell->face(f)->line(j)->vertex(0).norm() - cell->face(f)->line(j)->vertex(1).norm()) < eps) - cell->face(f)->line(j)->set_boundary_indicator(1); + for (unsigned int j=0; j<8; ++j) + cells[i].vertices[j] = cell_vertices[i][j]; + cells[i].material_id = 0; } - else - AssertThrow (false, ExcInternalError()); + + tria.create_triangulation ( vertices, cells, SubCellData()); // no boundary information + } + else + { + AssertThrow(false, ExcNotImplemented()); } -} + if (colorize) + colorize_quarter_hyper_shell(tria, center, inner_radius, outer_radius); + } // Implementation for 3D only -template <> -void GridGenerator::quarter_hyper_shell (Triangulation<3> &tria, - const Point<3> ¢er, - const double inner_radius, - const double outer_radius, - const size_type n, - const bool colorize) -{ - Assert ((inner_radius > 0) && (inner_radius < outer_radius), - ExcInvalidRadii ()); - if (n == 0 || n == 3) - { - const double a = inner_radius*std::sqrt(2.0)/2e0; - const double b = outer_radius*std::sqrt(2.0)/2e0; - const double c = a*std::sqrt(3.0)/2e0; - const double d = b*std::sqrt(3.0)/2e0; - const double e = outer_radius/2e0; - const double h = inner_radius/2e0; - - std::vector > vertices; - - vertices.push_back (center+Point<3>( 0, inner_radius, 0)); //0 - vertices.push_back (center+Point<3>( a, a, 0)); //1 - vertices.push_back (center+Point<3>( b, b, 0)); //2 - vertices.push_back (center+Point<3>( 0, outer_radius, 0)); //3 - vertices.push_back (center+Point<3>( 0, a , a)); //4 - vertices.push_back (center+Point<3>( c, c , h)); //5 - vertices.push_back (center+Point<3>( d, d , e)); //6 - vertices.push_back (center+Point<3>( 0, b , b)); //7 - vertices.push_back (center+Point<3>( inner_radius, 0 , 0)); //8 - vertices.push_back (center+Point<3>( outer_radius, 0 , 0)); //9 - vertices.push_back (center+Point<3>( a, 0 , a)); //10 - vertices.push_back (center+Point<3>( b, 0 , b)); //11 - vertices.push_back (center+Point<3>( 0, 0 , inner_radius)); //12 - vertices.push_back (center+Point<3>( 0, 0 , outer_radius)); //13 - - const int cell_vertices[3][8] = - { - {0, 1, 3, 2, 4, 5, 7, 6}, - {1, 8, 2, 9, 5, 10, 6, 11}, - {4, 5, 7, 6, 12, 10, 13, 11}, + template <> + void cylinder_shell (Triangulation<3> &tria, + const double length, + const double inner_radius, + const double outer_radius, + const unsigned int n_radial_cells, + const unsigned int n_axial_cells) + { + Assert ((inner_radius > 0) && (inner_radius < outer_radius), + ExcInvalidRadii ()); + + const double pi = numbers::PI; + + // determine the number of cells + // for the grid. if not provided by + // the user determine it such that + // the length of each cell on the + // median (in the middle between + // the two circles) is equal to its + // radial extent (which is the + // difference between the two + // radii) + const unsigned int N_r = (n_radial_cells == 0 ? + static_cast + (std::ceil((2*pi* (outer_radius + inner_radius)/2) / + (outer_radius - inner_radius))) : + n_radial_cells); + const unsigned int N_z = (n_axial_cells == 0 ? + static_cast + (std::ceil (length / + (2*pi*(outer_radius + inner_radius)/2/N_r))) : + n_axial_cells); + + // set up N vertices on the + // outer and N vertices on + // the inner circle. the + // first N ones are on the + // outer one, and all are + // numbered counter-clockwise + std::vector > vertices_2d(2*N_r); + for (unsigned int i=0; i( std::cos(2*pi * i/N_r), + std::sin(2*pi * i/N_r)) * outer_radius; + vertices_2d[i+N_r] = vertices_2d[i] * (inner_radius/outer_radius); }; - std::vector > cells(3); - for (unsigned int i=0; i<3; ++i) + std::vector > vertices_3d; + vertices_3d.reserve (2*N_r*(N_z+1)); + for (unsigned int j=0; j<=N_z; ++j) + for (unsigned int i=0; i<2*N_r; ++i) { - for (unsigned int j=0; j<8; ++j) - cells[i].vertices[j] = cell_vertices[i][j]; - cells[i].material_id = 0; + const Point<3> v (vertices_2d[i][0], + vertices_2d[i][1], + j*length/N_z); + vertices_3d.push_back (v); } - tria.create_triangulation ( vertices, cells, SubCellData()); // no boundary information - } - else - { - AssertThrow(false, ExcNotImplemented()); - } - - if (colorize) - colorize_quarter_hyper_shell(tria, center, inner_radius, outer_radius); -} + std::vector > cells (N_r*N_z, CellData<3>()); + for (unsigned int j=0; j -void GridGenerator::cylinder_shell (Triangulation<3> &tria, - const double length, - const double inner_radius, - const double outer_radius, - const size_type n_radial_cells, - const size_type n_axial_cells) -{ - Assert ((inner_radius > 0) && (inner_radius < outer_radius), - ExcInvalidRadii ()); - - const double pi = numbers::PI; - - // determine the number of cells - // for the grid. if not provided by - // the user determine it such that - // the length of each cell on the - // median (in the middle between - // the two circles) is equal to its - // radial extent (which is the - // difference between the two - // radii) - const size_type N_r = (n_radial_cells == 0 ? - static_cast - (std::ceil((2*pi* (outer_radius + inner_radius)/2) / - (outer_radius - inner_radius))) : - n_radial_cells); - const size_type N_z = (n_axial_cells == 0 ? - static_cast - (std::ceil (length / - (2*pi*(outer_radius + inner_radius)/2/N_r))) : - n_axial_cells); - - // set up N vertices on the - // outer and N vertices on - // the inner circle. the - // first N ones are on the - // outer one, and all are - // numbered counter-clockwise - std::vector > vertices_2d(2*N_r); - for (size_type i=0; i( std::cos(2*pi * i/N_r), - std::sin(2*pi * i/N_r)) * outer_radius; - vertices_2d[i+N_r] = vertices_2d[i] * (inner_radius/outer_radius); - }; + cells[i+j*N_r].vertices[4] = N_r+i + (j+1)*2*N_r; + cells[i+j*N_r].vertices[5] = N_r+((i+1)%N_r) + (j+1)*2*N_r; + cells[i+j*N_r].vertices[6] = N_r+i + j*2*N_r; + cells[i+j*N_r].vertices[7] = N_r+((i+1)%N_r) + j*2*N_r; - std::vector > vertices_3d; - vertices_3d.reserve (2*N_r*(N_z+1)); - for (size_type j=0; j<=N_z; ++j) - for (size_type i=0; i<2*N_r; ++i) - { - const Point<3> v (vertices_2d[i][0], - vertices_2d[i][1], - j*length/N_z); - vertices_3d.push_back (v); - } + cells[i+j*N_r].material_id = 0; + } - std::vector > cells (N_r*N_z, CellData<3>()); + tria.create_triangulation ( + vertices_3d, cells, SubCellData()); + } - for (size_type j=0; j + void + merge_triangulations (const Triangulation &triangulation_1, + const Triangulation &triangulation_2, + Triangulation &result) + { + Assert (triangulation_1.n_levels() == 1, + ExcMessage ("The input triangulations must be coarse meshes.")); + Assert (triangulation_2.n_levels() == 1, + ExcMessage ("The input triangulations must be coarse meshes.")); + + // get the union of the set of vertices + std::vector > vertices = triangulation_1.get_vertices(); + vertices.insert (vertices.end(), + triangulation_2.get_vertices().begin(), + triangulation_2.get_vertices().end()); + + // now form the union of the set of cells + std::vector > cells; + cells.reserve (triangulation_1.n_cells() + triangulation_2.n_cells()); + for (typename Triangulation::cell_iterator + cell = triangulation_1.begin(); cell != triangulation_1.end(); ++cell) + { + CellData this_cell; + for (unsigned int v=0; v::vertices_per_cell; ++v) + this_cell.vertices[v] = cell->vertex_index(v); + this_cell.material_id = cell->material_id(); + cells.push_back (this_cell); } - tria.create_triangulation ( - vertices_3d, cells, SubCellData()); -} - - - -template -void -GridGenerator:: -merge_triangulations (const Triangulation &triangulation_1, - const Triangulation &triangulation_2, - Triangulation &result) -{ - Assert (triangulation_1.n_levels() == 1, - ExcMessage ("The input triangulations must be coarse meshes.")); - Assert (triangulation_2.n_levels() == 1, - ExcMessage ("The input triangulations must be coarse meshes.")); - - // get the union of the set of vertices - std::vector > vertices = triangulation_1.get_vertices(); - vertices.insert (vertices.end(), - triangulation_2.get_vertices().begin(), - triangulation_2.get_vertices().end()); - - // now form the union of the set of cells - std::vector > cells; - cells.reserve (triangulation_1.n_cells() + triangulation_2.n_cells()); - for (typename Triangulation::cell_iterator - cell = triangulation_1.begin(); cell != triangulation_1.end(); ++cell) - { - CellData this_cell; - for (unsigned int v=0; v::vertices_per_cell; ++v) - this_cell.vertices[v] = cell->vertex_index(v); - this_cell.material_id = cell->material_id(); - cells.push_back (this_cell); - } - - // now do the same for the other other mesh. note that we have to - // translate the vertex indices - for (typename Triangulation::cell_iterator - cell = triangulation_2.begin(); cell != triangulation_2.end(); ++cell) - { - CellData this_cell; - for (unsigned int v=0; v::vertices_per_cell; ++v) - this_cell.vertices[v] = cell->vertex_index(v) + triangulation_1.n_vertices(); - this_cell.material_id = cell->material_id(); - cells.push_back (this_cell); - } - - // throw out duplicated vertices from the two meshes - // and create the triangulation - SubCellData subcell_data; - std::vector considered_vertices; - GridTools::delete_duplicated_vertices (vertices, cells, subcell_data, considered_vertices); - result.clear (); - result.create_triangulation (vertices, cells, subcell_data); -} - -void -GridGenerator:: -extrude_triangulation(const Triangulation<2, 2> &input, - const size_type n_slices, - const double height, - Triangulation<3,3> &result) -{ - Assert (input.n_levels() == 1, - ExcMessage ("The input triangulations must be coarse meshes.")); - Assert(result.n_cells()==0, ExcMessage("resultin Triangulation need to be empty upon calling extrude_triangulation.")); - Assert(height>0, ExcMessage("The height in extrude_triangulation needs to be positive.")); - Assert(n_slices>=2, ExcMessage("The number of slices in extrude_triangulation needs to be at least 2.")); - - std::vector > points(n_slices*input.n_vertices()); - std::vector > cells; - cells.reserve((n_slices-1)*input.n_active_cells()); + // now do the same for the other other mesh. note that we have to + // translate the vertex indices + for (typename Triangulation::cell_iterator + cell = triangulation_2.begin(); cell != triangulation_2.end(); ++cell) + { + CellData this_cell; + for (unsigned int v=0; v::vertices_per_cell; ++v) + this_cell.vertices[v] = cell->vertex_index(v) + triangulation_1.n_vertices(); + this_cell.material_id = cell->material_id(); + cells.push_back (this_cell); + } - for (size_type slice=0; slice considered_vertices; + GridTools::delete_duplicated_vertices (vertices, cells, subcell_data, considered_vertices); + result.clear (); + result.create_triangulation (vertices, cells, subcell_data); + } + + + void + extrude_triangulation(const Triangulation<2, 2> &input, + const unsigned int n_slices, + const double height, + Triangulation<3,3> &result) + { + Assert (input.n_levels() == 1, + ExcMessage ("The input triangulations must be coarse meshes.")); + Assert(result.n_cells()==0, ExcMessage("resultin Triangulation need to be empty upon calling extrude_triangulation.")); + Assert(height>0, ExcMessage("The height in extrude_triangulation needs to be positive.")); + Assert(n_slices>=2, ExcMessage("The number of slices in extrude_triangulation needs to be at least 2.")); - { - const Point<2> &v = input.get_vertices()[i]; - points[i+slice*input.n_vertices()](0) = v(0); - points[i+slice*input.n_vertices()](1) = v(1); - points[i+slice*input.n_vertices()](2) = height * slice / (n_slices-1); - } - } + std::vector > points(n_slices*input.n_vertices()); + std::vector > cells; + cells.reserve((n_slices-1)*input.n_active_cells()); - for (Triangulation<2,2>::cell_iterator - cell = input.begin(); cell != input.end(); ++cell) - { - for (size_type slice=0; slice this_cell; - for (unsigned int v=0; v::vertices_per_cell; ++v) - { - this_cell.vertices[v] - = cell->vertex_index(v)+slice*input.n_vertices(); - this_cell.vertices[v+GeometryInfo<2>::vertices_per_cell] - = cell->vertex_index(v)+(slice+1)*input.n_vertices(); - } + for (unsigned int slice=0; slicematerial_id(); - cells.push_back(this_cell); - } - } + { + const Point<2> &v = input.get_vertices()[i]; + points[i+slice*input.n_vertices()](0) = v(0); + points[i+slice*input.n_vertices()](1) = v(1); + points[i+slice*input.n_vertices()](2) = height * slice / (n_slices-1); + } + } - SubCellData s; - types::boundary_id bid=0; - s.boundary_quads.reserve(input.n_active_lines()*(n_slices-1) + input.n_active_cells()*2); - for (Triangulation<2,2>::cell_iterator - cell = input.begin(); cell != input.end(); ++cell) - { - CellData<2> quad; - for (unsigned int f=0; f<4; ++f) - if (cell->at_boundary(f)) + for (Triangulation<2,2>::cell_iterator + cell = input.begin(); cell != input.end(); ++cell) + { + for (unsigned int slice=0; sliceface(f)->boundary_indicator(); - bid = std::max(bid, quad.boundary_id); - for (size_type slice=0; slice this_cell; + for (unsigned int v=0; v::vertices_per_cell; ++v) { - quad.vertices[0] = cell->face(f)->vertex_index(0)+slice*input.n_vertices(); - quad.vertices[1] = cell->face(f)->vertex_index(1)+slice*input.n_vertices(); - quad.vertices[2] = cell->face(f)->vertex_index(0)+(slice+1)*input.n_vertices(); - quad.vertices[3] = cell->face(f)->vertex_index(1)+(slice+1)*input.n_vertices(); - s.boundary_quads.push_back(quad); + this_cell.vertices[v] + = cell->vertex_index(v)+slice*input.n_vertices(); + this_cell.vertices[v+GeometryInfo<2>::vertices_per_cell] + = cell->vertex_index(v)+(slice+1)*input.n_vertices(); } - } - } - for (Triangulation<2,2>::cell_iterator - cell = input.begin(); cell != input.end(); ++cell) - { - CellData<2> quad; - quad.boundary_id = bid + 1; - quad.vertices[0] = cell->vertex_index(0); - quad.vertices[1] = cell->vertex_index(1); - quad.vertices[2] = cell->vertex_index(2); - quad.vertices[3] = cell->vertex_index(3); - s.boundary_quads.push_back(quad); - - quad.boundary_id = bid + 2; - for (int i=0; i<4; ++i) - quad.vertices[i] += (n_slices-1)*input.n_vertices(); - s.boundary_quads.push_back(quad); - } + this_cell.material_id = cell->material_id(); + cells.push_back(this_cell); + } + } + SubCellData s; + types::boundary_id bid=0; + s.boundary_quads.reserve(input.n_active_lines()*(n_slices-1) + input.n_active_cells()*2); + for (Triangulation<2,2>::cell_iterator + cell = input.begin(); cell != input.end(); ++cell) + { + CellData<2> quad; + for (unsigned int f=0; f<4; ++f) + if (cell->at_boundary(f)) + { + quad.boundary_id = cell->face(f)->boundary_indicator(); + bid = std::max(bid, quad.boundary_id); + for (unsigned int slice=0; sliceface(f)->vertex_index(0)+slice*input.n_vertices(); + quad.vertices[1] = cell->face(f)->vertex_index(1)+slice*input.n_vertices(); + quad.vertices[2] = cell->face(f)->vertex_index(0)+(slice+1)*input.n_vertices(); + quad.vertices[3] = cell->face(f)->vertex_index(1)+(slice+1)*input.n_vertices(); + s.boundary_quads.push_back(quad); + } + } + } + for (Triangulation<2,2>::cell_iterator + cell = input.begin(); cell != input.end(); ++cell) + { + CellData<2> quad; + quad.boundary_id = bid + 1; + quad.vertices[0] = cell->vertex_index(0); + quad.vertices[1] = cell->vertex_index(1); + quad.vertices[2] = cell->vertex_index(2); + quad.vertices[3] = cell->vertex_index(3); + s.boundary_quads.push_back(quad); + + quad.boundary_id = bid + 2; + for (int i=0; i<4; ++i) + quad.vertices[i] += (n_slices-1)*input.n_vertices(); + s.boundary_quads.push_back(quad); + } - result.create_triangulation ( - points, - cells, - s); -} + result.create_triangulation (points, + cells, + s); + } -// make the following function inline. this is so that it becomes marked -// internal/weak for the linker and we don't get multiply defined errors -// when linking with more than one dimension at a time. Usually we used -// the trick of putting these functions in a .all_dimensions.cc file, but -// this is not necessary here as this is an internal only function. -inline -void GridGenerator::laplace_solve (const SparseMatrix &S, - const std::map &m, - Vector &u) -{ - const size_type n_dofs=S.n(); - FilteredMatrix > SF (S); - PreconditionJacobi > prec; - prec.initialize(S, 1.2); - FilteredMatrix > PF (prec); + /** + * Solve the Laplace equation for @p laplace_transformation function for one + * of the @p dim space dimensions. Factorized into a function of its own + * in order to allow parallel execution. + */ + void laplace_solve (const SparseMatrix &S, + const std::map &m, + Vector &u) + { + const unsigned int n_dofs=S.n(); + FilteredMatrix > SF (S); + PreconditionJacobi > prec; + prec.initialize(S, 1.2); + FilteredMatrix > PF (prec); - SolverControl control (n_dofs, 1.e-10, false, false); - GrowingVectorMemory > mem; - SolverCG > solver (control, mem); + SolverControl control (n_dofs, 1.e-10, false, false); + GrowingVectorMemory > mem; + SolverCG > solver (control, mem); - Vector f(n_dofs); + Vector f(n_dofs); - SF.add_constraints(m); - SF.apply_constraints (f, true); - solver.solve(SF, u, f, PF); -} + SF.add_constraints(m); + SF.apply_constraints (f, true); + solver.solve(SF, u, f, PF); + } // Implementation for 1D only -template <> -void GridGenerator::laplace_transformation (Triangulation<1> &, - const std::map > &) -{ - Assert(false, ExcNotImplemented()); -} + template <> + void laplace_transformation (Triangulation<1> &, + const std::map > &) + { + Assert(false, ExcNotImplemented()); + } // Implementation for dimensions except 1 -template -void GridGenerator::laplace_transformation (Triangulation &tria, - const std::map > &new_points) -{ - // first provide everything that is - // needed for solving a Laplace - // equation. - MappingQ1 mapping_q1; - FE_Q q1(1); - - DoFHandler dof_handler(tria); - dof_handler.distribute_dofs(q1); - - CompressedSparsityPattern c_sparsity_pattern (dof_handler.n_dofs (), - dof_handler.n_dofs ()); - DoFTools::make_sparsity_pattern (dof_handler, c_sparsity_pattern); - c_sparsity_pattern.compress (); - - SparsityPattern sparsity_pattern; - sparsity_pattern.copy_from (c_sparsity_pattern); - sparsity_pattern.compress (); - - SparseMatrix S(sparsity_pattern); - - QGauss quadrature(4); - - MatrixCreator::create_laplace_matrix(mapping_q1, dof_handler, quadrature, S); - - // set up the boundary values for - // the laplace problem - std::vector > m(dim); - typename std::map >::const_iterator map_iter; - typename std::map >::const_iterator map_end=new_points.end(); - - // fill these maps using the data - // given by new_points - typename DoFHandler::cell_iterator cell=dof_handler.begin_active(), - endc=dof_handler.end(); - typename DoFHandler::face_iterator face; - for (; cell!=endc; ++cell) - { - if (cell->at_boundary()) - for (unsigned int face_no=0; face_no::faces_per_cell; ++face_no) - { - face=cell->face(face_no); - if (face->at_boundary()) - for (unsigned int vertex_no=0; - vertex_no::vertices_per_face; ++vertex_no) - { - const size_type vertex_index=face->vertex_index(vertex_no); - map_iter=new_points.find(vertex_index); - - if (map_iter!=map_end) - for (unsigned int i=0; i ( - face->vertex_dof_index(vertex_no, 0), map_iter->second(i))); - } - } - } + template + void laplace_transformation (Triangulation &tria, + const std::map > &new_points) + { + // first provide everything that is + // needed for solving a Laplace + // equation. + MappingQ1 mapping_q1; + FE_Q q1(1); + + DoFHandler dof_handler(tria); + dof_handler.distribute_dofs(q1); + + CompressedSparsityPattern c_sparsity_pattern (dof_handler.n_dofs (), + dof_handler.n_dofs ()); + DoFTools::make_sparsity_pattern (dof_handler, c_sparsity_pattern); + c_sparsity_pattern.compress (); + + SparsityPattern sparsity_pattern; + sparsity_pattern.copy_from (c_sparsity_pattern); + sparsity_pattern.compress (); + + SparseMatrix S(sparsity_pattern); + + QGauss quadrature(4); + + MatrixCreator::create_laplace_matrix(mapping_q1, dof_handler, quadrature, S); + + // set up the boundary values for + // the laplace problem + std::vector > m(dim); + typename std::map >::const_iterator map_iter; + typename std::map >::const_iterator map_end=new_points.end(); + + // fill these maps using the data + // given by new_points + typename DoFHandler::cell_iterator cell=dof_handler.begin_active(), + endc=dof_handler.end(); + typename DoFHandler::face_iterator face; + for (; cell!=endc; ++cell) + { + if (cell->at_boundary()) + for (unsigned int face_no=0; face_no::faces_per_cell; ++face_no) + { + face=cell->face(face_no); + if (face->at_boundary()) + for (unsigned int vertex_no=0; + vertex_no::vertices_per_face; ++vertex_no) + { + const unsigned int vertex_index=face->vertex_index(vertex_no); + map_iter=new_points.find(vertex_index); - // solve the dim problems with - // different right hand sides. - Vector us[dim]; - for (unsigned int i=0; i tasks; - for (unsigned int i=0; i::vertices_per_cell; ++vertex_no) - { - Point &v=cell->vertex(vertex_no); - const size_type dof_index=cell->vertex_dof_index(vertex_no, 0); - for (unsigned int i=0; i ( + face->vertex_dof_index(vertex_no, 0), map_iter->second(i))); + } + } } -} + // solve the dim problems with + // different right hand sides. + Vector us[dim]; + for (unsigned int i=0; i tasks; + for (unsigned int i=0; i::vertices_per_cell; ++vertex_no) + { + Point &v=cell->vertex(vertex_no); + const unsigned int dof_index=cell->vertex_dof_index(vertex_no, 0); + for (unsigned int i=0; i -void GridGenerator::hyper_cube_with_cylindrical_hole (Triangulation<1> &, - const double, - const double, - const double, - const size_type, - bool) -{ - Assert(false, ExcNotImplemented()); -} + template <> + void hyper_cube_with_cylindrical_hole (Triangulation<1> &, + const double, + const double, + const double, + const unsigned int, + bool) + { + Assert(false, ExcNotImplemented()); + } -template <> -void -GridGenerator::hyper_cube_with_cylindrical_hole (Triangulation<2> &triangulation, - const double inner_radius, - const double outer_radius, - const double, // width, - const size_type, // width_repetition, - bool colorize) -{ - const int dim = 2; - - Assert(inner_radius < outer_radius, - ExcMessage("outer_radius has to be bigger than inner_radius.")); - - Point center; - // We create an hyper_shell in two dimensions, and then we modify it. - GridGenerator::hyper_shell (triangulation, - center, inner_radius, outer_radius, - 8); - Triangulation::active_cell_iterator - cell = triangulation.begin_active(), - endc = triangulation.end(); - std::vector treated_vertices(triangulation.n_vertices(), false); - for (; cell != endc; ++cell) - { - for (unsigned int f=0; f::faces_per_cell; ++f) - if (cell->face(f)->at_boundary()) - { - for (unsigned int v=0; v < GeometryInfo::vertices_per_face; ++v) - { - size_type vv = cell->face(f)->vertex_index(v); - if (treated_vertices[vv] == false) - { - treated_vertices[vv] = true; - switch (vv) - { - case 1: - cell->face(f)->vertex(v) = center+Point(outer_radius,outer_radius); - break; - case 3: - cell->face(f)->vertex(v) = center+Point(-outer_radius,outer_radius); - break; - case 5: - cell->face(f)->vertex(v) = center+Point(-outer_radius,-outer_radius); - break; - case 7: - cell->face(f)->vertex(v) = center+Point(outer_radius,-outer_radius); - default: - break; - } - } - } - } - } - double eps = 1e-3 * outer_radius; - cell = triangulation.begin_active(); - for (; cell != endc; ++cell) - { - for (unsigned int f=0; f::faces_per_cell; ++f) - if (cell->face(f)->at_boundary()) - { - double dx = cell->face(f)->center()(0) - center(0); - double dy = cell->face(f)->center()(1) - center(1); - if (colorize) - { - if (std::abs(dx + outer_radius) < eps) - cell->face(f)->set_boundary_indicator(0); - else if (std::abs(dx - outer_radius) < eps) - cell->face(f)->set_boundary_indicator(1); - else if (std::abs(dy + outer_radius) < eps) - cell->face(f)->set_boundary_indicator(2); - else if (std::abs(dy - outer_radius) < eps) - cell->face(f)->set_boundary_indicator(3); - else - cell->face(f)->set_boundary_indicator(4); - } - else - { - double d = (cell->face(f)->center() - center).norm(); - if (d-inner_radius < 0) - cell->face(f)->set_boundary_indicator(1); - else - cell->face(f)->set_boundary_indicator(0); - } - } - } -} -template <> -void GridGenerator::hyper_cube_with_cylindrical_hole(Triangulation<3> &triangulation, - const double inner_radius, - const double outer_radius, - const double L, - const size_type Nz, - bool colorize) -{ - const int dim = 3; - - Assert(inner_radius < outer_radius, - ExcMessage("outer_radius has to be bigger than inner_radius.")); - Assert(L > 0, - ExcMessage("Must give positive extension L")); - Assert(Nz >= 1, ExcLowerRange(1, Nz)); - - GridGenerator::cylinder_shell (triangulation, - L, inner_radius, outer_radius, - 8, - Nz); - - Triangulation::active_cell_iterator - cell = triangulation.begin_active(), - endc = triangulation.end(); - std::vector treated_vertices(triangulation.n_vertices(), false); - for (; cell != endc; ++cell) - { - for (unsigned int f=0; f::faces_per_cell; ++f) - if (cell->face(f)->at_boundary()) - { - for (unsigned int v=0; v < GeometryInfo::vertices_per_face; ++v) - { - size_type vv = cell->face(f)->vertex_index(v); - if (treated_vertices[vv] == false) - { - treated_vertices[vv] = true; - for (size_type i=0; i<=Nz; ++i) - { - double d = ((double) i)*L/((double) Nz); - switch (vv-i*16) - { - case 1: - cell->face(f)->vertex(v) = Point(outer_radius,outer_radius,d); - break; - case 3: - cell->face(f)->vertex(v) = Point(-outer_radius,outer_radius,d); - break; - case 5: - cell->face(f)->vertex(v) = Point(-outer_radius,-outer_radius,d); - break; - case 7: - cell->face(f)->vertex(v) = Point(outer_radius,-outer_radius,d); - break; - default: - break; - } - } - } - } - } - } - double eps = 1e-3 * outer_radius; - cell = triangulation.begin_active(); - for (; cell != endc; ++cell) - { - for (unsigned int f=0; f::faces_per_cell; ++f) - if (cell->face(f)->at_boundary()) - { - double dx = cell->face(f)->center()(0); - double dy = cell->face(f)->center()(1); - double dz = cell->face(f)->center()(2); + template <> + void + hyper_cube_with_cylindrical_hole (Triangulation<2> &triangulation, + const double inner_radius, + const double outer_radius, + const double, // width, + const unsigned int, // width_repetition, + bool colorize) + { + const int dim = 2; + + Assert(inner_radius < outer_radius, + ExcMessage("outer_radius has to be bigger than inner_radius.")); + + Point center; + // We create an hyper_shell in two dimensions, and then we modify it. + hyper_shell (triangulation, + center, inner_radius, outer_radius, + 8); + Triangulation::active_cell_iterator + cell = triangulation.begin_active(), + endc = triangulation.end(); + std::vector treated_vertices(triangulation.n_vertices(), false); + for (; cell != endc; ++cell) + { + for (unsigned int f=0; f::faces_per_cell; ++f) + if (cell->face(f)->at_boundary()) + { + for (unsigned int v=0; v < GeometryInfo::vertices_per_face; ++v) + { + unsigned int vv = cell->face(f)->vertex_index(v); + if (treated_vertices[vv] == false) + { + treated_vertices[vv] = true; + switch (vv) + { + case 1: + cell->face(f)->vertex(v) = center+Point(outer_radius,outer_radius); + break; + case 3: + cell->face(f)->vertex(v) = center+Point(-outer_radius,outer_radius); + break; + case 5: + cell->face(f)->vertex(v) = center+Point(-outer_radius,-outer_radius); + break; + case 7: + cell->face(f)->vertex(v) = center+Point(outer_radius,-outer_radius); + default: + break; + } + } + } + } + } + double eps = 1e-3 * outer_radius; + cell = triangulation.begin_active(); + for (; cell != endc; ++cell) + { + for (unsigned int f=0; f::faces_per_cell; ++f) + if (cell->face(f)->at_boundary()) + { + double dx = cell->face(f)->center()(0) - center(0); + double dy = cell->face(f)->center()(1) - center(1); + if (colorize) + { + if (std::abs(dx + outer_radius) < eps) + cell->face(f)->set_boundary_indicator(0); + else if (std::abs(dx - outer_radius) < eps) + cell->face(f)->set_boundary_indicator(1); + else if (std::abs(dy + outer_radius) < eps) + cell->face(f)->set_boundary_indicator(2); + else if (std::abs(dy - outer_radius) < eps) + cell->face(f)->set_boundary_indicator(3); + else + cell->face(f)->set_boundary_indicator(4); + } + else + { + double d = (cell->face(f)->center() - center).norm(); + if (d-inner_radius < 0) + cell->face(f)->set_boundary_indicator(1); + else + cell->face(f)->set_boundary_indicator(0); + } + } + } + } - if (colorize) - { - if (std::abs(dx + outer_radius) < eps) - cell->face(f)->set_boundary_indicator(0); - else if (std::abs(dx - outer_radius) < eps) - cell->face(f)->set_boundary_indicator(1); - else if (std::abs(dy + outer_radius) < eps) - cell->face(f)->set_boundary_indicator(2); + template <> + void hyper_cube_with_cylindrical_hole(Triangulation<3> &triangulation, + const double inner_radius, + const double outer_radius, + const double L, + const unsigned int Nz, + bool colorize) + { + const int dim = 3; + + Assert(inner_radius < outer_radius, + ExcMessage("outer_radius has to be bigger than inner_radius.")); + Assert(L > 0, + ExcMessage("Must give positive extension L")); + Assert(Nz >= 1, ExcLowerRange(1, Nz)); + + cylinder_shell (triangulation, + L, inner_radius, outer_radius, + 8, + Nz); + + Triangulation::active_cell_iterator + cell = triangulation.begin_active(), + endc = triangulation.end(); + std::vector treated_vertices(triangulation.n_vertices(), false); + for (; cell != endc; ++cell) + { + for (unsigned int f=0; f::faces_per_cell; ++f) + if (cell->face(f)->at_boundary()) + { + for (unsigned int v=0; v < GeometryInfo::vertices_per_face; ++v) + { + unsigned int vv = cell->face(f)->vertex_index(v); + if (treated_vertices[vv] == false) + { + treated_vertices[vv] = true; + for (unsigned int i=0; i<=Nz; ++i) + { + double d = ((double) i)*L/((double) Nz); + switch (vv-i*16) + { + case 1: + cell->face(f)->vertex(v) = Point(outer_radius,outer_radius,d); + break; + case 3: + cell->face(f)->vertex(v) = Point(-outer_radius,outer_radius,d); + break; + case 5: + cell->face(f)->vertex(v) = Point(-outer_radius,-outer_radius,d); + break; + case 7: + cell->face(f)->vertex(v) = Point(outer_radius,-outer_radius,d); + break; + default: + break; + } + } + } + } + } + } + double eps = 1e-3 * outer_radius; + cell = triangulation.begin_active(); + for (; cell != endc; ++cell) + { + for (unsigned int f=0; f::faces_per_cell; ++f) + if (cell->face(f)->at_boundary()) + { + double dx = cell->face(f)->center()(0); + double dy = cell->face(f)->center()(1); + double dz = cell->face(f)->center()(2); - else if (std::abs(dy - outer_radius) < eps) - cell->face(f)->set_boundary_indicator(3); + if (colorize) + { + if (std::abs(dx + outer_radius) < eps) + cell->face(f)->set_boundary_indicator(0); - else if (std::abs(dz) < eps) - cell->face(f)->set_boundary_indicator(4); + else if (std::abs(dx - outer_radius) < eps) + cell->face(f)->set_boundary_indicator(1); - else if (std::abs(dz - L) < eps) - cell->face(f)->set_boundary_indicator(5); + else if (std::abs(dy + outer_radius) < eps) + cell->face(f)->set_boundary_indicator(2); - else - { - cell->face(f)->set_boundary_indicator(6); - for (unsigned int l=0; l::lines_per_face; ++l) - cell->face(f)->line(l)->set_boundary_indicator(6); - } + else if (std::abs(dy - outer_radius) < eps) + cell->face(f)->set_boundary_indicator(3); - } - else - { - Point c = cell->face(f)->center(); - c(2) = 0; - double d = c.norm(); - if (d-inner_radius < 0) - { - cell->face(f)->set_boundary_indicator(1); - for (unsigned int l=0; l::lines_per_face; ++l) - cell->face(f)->line(l)->set_boundary_indicator(1); - } - else - cell->face(f)->set_boundary_indicator(0); - } - } - } -} + else if (std::abs(dz) < eps) + cell->face(f)->set_boundary_indicator(4); + + else if (std::abs(dz - L) < eps) + cell->face(f)->set_boundary_indicator(5); + + else + { + cell->face(f)->set_boundary_indicator(6); + for (unsigned int l=0; l::lines_per_face; ++l) + cell->face(f)->line(l)->set_boundary_indicator(6); + } + } + else + { + Point c = cell->face(f)->center(); + c(2) = 0; + double d = c.norm(); + if (d-inner_radius < 0) + { + cell->face(f)->set_boundary_indicator(1); + for (unsigned int l=0; l::lines_per_face; ++l) + cell->face(f)->line(l)->set_boundary_indicator(1); + } + else + cell->face(f)->set_boundary_indicator(0); + } + } + } + } +} // explicit instantiations #include "grid_generator.inst" diff --git a/deal.II/source/grid/grid_generator.inst.in b/deal.II/source/grid/grid_generator.inst.in index fadcea0bc7..5ce5fcc0f4 100644 --- a/deal.II/source/grid/grid_generator.inst.in +++ b/deal.II/source/grid/grid_generator.inst.in @@ -17,42 +17,41 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS) { +namespace GridGenerator +\{ #if deal_II_dimension <= deal_II_space_dimension template void - GridGenerator::hyper_rectangle ( + hyper_rectangle ( Triangulation &, const Point&, const Point&, const bool); template void - GridGenerator::colorize_hyper_rectangle ( - Triangulation &); - - template void - GridGenerator::hyper_cube ( + hyper_cube ( Triangulation &, const double, const double); template void - GridGenerator::merge_triangulations + merge_triangulations (const Triangulation &triangulation_1, const Triangulation &triangulation_2, Triangulation &result); #endif +\} } for (deal_II_dimension : DIMENSIONS) { - +namespace GridGenerator \{ template void - GridGenerator::subdivided_hyper_cube ( + subdivided_hyper_cube ( Triangulation &, const unsigned int, const double, const double); template void - GridGenerator::subdivided_hyper_rectangle + subdivided_hyper_rectangle (Triangulation &, const std::vector&, const Point&, @@ -61,7 +60,7 @@ for (deal_II_dimension : DIMENSIONS) template void - GridGenerator::subdivided_hyper_rectangle( + subdivided_hyper_rectangle( Triangulation &, const std::vector > &, const Point &, @@ -69,32 +68,31 @@ for (deal_II_dimension : DIMENSIONS) const bool ); template void - GridGenerator::parallelepiped ( + parallelepiped ( Triangulation&, const Point (&) [deal_II_dimension], const bool); template void - GridGenerator::subdivided_parallelepiped ( + subdivided_parallelepiped ( Triangulation&, - const size_type, + const unsigned int, const Point (&) [deal_II_dimension], const bool); template void - GridGenerator::subdivided_parallelepiped ( + subdivided_parallelepiped ( Triangulation&, - const size_type [deal_II_dimension], + const unsigned int [deal_II_dimension], const Point (&) [deal_II_dimension], const bool); #if deal_II_dimension > 1 template void - GridGenerator:: laplace_transformation (Triangulation &, - const std::map > &); + const std::map > &); #endif - +\} } diff --git a/deal.II/source/grid/grid_tools.cc b/deal.II/source/grid/grid_tools.cc index ed2325f2b1..a49ede55e2 100644 --- a/deal.II/source/grid/grid_tools.cc +++ b/deal.II/source/grid/grid_tools.cc @@ -607,7 +607,7 @@ namespace GridTools template void - laplace_transform (const std::map > &new_points, + laplace_transform (const std::map > &new_points, Triangulation &triangulation) { //TODO: Move implementation of this function into the current diff --git a/deal.II/source/grid/grid_tools.inst.in b/deal.II/source/grid/grid_tools.inst.in index 9087a8e74f..4411897224 100644 --- a/deal.II/source/grid/grid_tools.inst.in +++ b/deal.II/source/grid/grid_tools.inst.in @@ -161,7 +161,7 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS #if deal_II_dimension == deal_II_space_dimension template void - laplace_transform (const std::map > &new_points, + laplace_transform (const std::map > &new_points, Triangulation &triangulation); template diff --git a/deal.II/source/lac/chunk_sparsity_pattern.cc b/deal.II/source/lac/chunk_sparsity_pattern.cc index a9e5b9de0b..021d90b89b 100644 --- a/deal.II/source/lac/chunk_sparsity_pattern.cc +++ b/deal.II/source/lac/chunk_sparsity_pattern.cc @@ -265,22 +265,26 @@ namespace internal // distinguish between compressed sparsity types that define row_begin() // and SparsityPattern that uses begin() as iterator type template - void copy_row (const Sparsity &csp, - const size_type row, - ChunkSparsityPattern &dst) + void copy_row (const Sparsity &csp, + const size_type row, + const unsigned int chunk_size, + CompressedSimpleSparsityPattern &dst) { typename Sparsity::row_iterator col_num = csp.row_begin (row); + const size_type reduced_row = row/chunk_size; for (; col_num != csp.row_end (row); ++col_num) - dst.add (row, *col_num); + dst.add (reduced_row, *col_num/chunk_size); } - void copy_row (const SparsityPattern &csp, - const size_type row, - ChunkSparsityPattern &dst) + void copy_row (const SparsityPattern &csp, + const size_type row, + const unsigned int chunk_size, + CompressedSimpleSparsityPattern &dst) { SparsityPattern::iterator col_num = csp.begin (row); + const size_type reduced_row = row/chunk_size; for (; col_num != csp.end (row); ++col_num) - dst.add (row, col_num->column()); + dst.add (reduced_row, col_num->column()/chunk_size); } } } @@ -292,23 +296,28 @@ ChunkSparsityPattern::copy_from (const SparsityType &csp, const size_type chunk_size) { Assert (chunk_size > 0, ExcInvalidNumber (chunk_size)); + this->chunk_size = chunk_size; + rows = csp.n_rows(); + cols = csp.n_cols(); - // count number of entries per row, then initialize the underlying sparsity - // pattern - std::vector entries_per_row (csp.n_rows(), 0); - for (size_type row = 0; row(*y), dst); AssertThrow (ierr == 0, ExcPETScError(ierr)); delete (x); diff --git a/deal.II/source/lac/petsc_parallel_sparse_matrix.cc b/deal.II/source/lac/petsc_parallel_sparse_matrix.cc index e366b66458..6e91035df7 100644 --- a/deal.II/source/lac/petsc_parallel_sparse_matrix.cc +++ b/deal.II/source/lac/petsc_parallel_sparse_matrix.cc @@ -43,6 +43,14 @@ namespace PETScWrappers } + SparseMatrix::~SparseMatrix () + { +#if DEAL_II_PETSC_VERSION_LT(3,2,0) + const int ierr = MatDestroy (matrix); +#else + const int ierr = MatDestroy (&matrix); +#endif + } SparseMatrix::SparseMatrix (const MPI_Comm &communicator, const size_type m, diff --git a/deal.II/source/lac/petsc_parallel_vector.cc b/deal.II/source/lac/petsc_parallel_vector.cc index 7c4cc997ee..848ba3eec1 100644 --- a/deal.II/source/lac/petsc_parallel_vector.cc +++ b/deal.II/source/lac/petsc_parallel_vector.cc @@ -39,6 +39,7 @@ namespace PETScWrappers const int ierr = VecCreateSeq (PETSC_COMM_SELF, n, &vector); AssertThrow (ierr == 0, ExcPETScError(ierr)); + ghosted = false; } @@ -130,7 +131,7 @@ namespace PETScWrappers MPI_Allreduce (&k, &k_global, 1, MPI_INT, MPI_LOR, communicator); - if (k_global) + if (k_global || has_ghost_elements()) { // FIXME: I'd like to use this here, // but somehow it leads to odd errors @@ -165,9 +166,17 @@ namespace PETScWrappers Vector::reinit (const Vector &v, const bool fast) { - communicator = v.communicator; - - reinit (communicator, v.size(), v.local_size(), fast); + if (v.has_ghost_elements()) + { + reinit (v.locally_owned_elements(), v.ghost_indices, v.communicator); + if (!fast) + { + int ierr = VecSet(vector, 0.0); + AssertThrow (ierr == 0, ExcPETScError(ierr)); + } + } + else + reinit (v.communicator, v.size(), v.local_size(), fast); } @@ -185,6 +194,14 @@ namespace PETScWrappers const IndexSet &ghost, const MPI_Comm &comm) { + int ierr; +#if DEAL_II_PETSC_VERSION_LT(3,2,0) + ierr = VecDestroy (vector); +#else + ierr = VecDestroy (&vector); +#endif + AssertThrow (ierr == 0, ExcPETScError(ierr)); + communicator = comm; Assert(local.is_contiguous(), ExcNotImplemented()); @@ -206,6 +223,14 @@ namespace PETScWrappers Vector::reinit (const IndexSet &local, const MPI_Comm &comm) { + int ierr; +#if DEAL_II_PETSC_VERSION_LT(3,2,0) + ierr = VecDestroy (vector); +#else + ierr = VecDestroy (&vector); +#endif + AssertThrow (ierr == 0, ExcPETScError(ierr)); + communicator = comm; Assert(local.is_contiguous(), ExcNotImplemented()); diff --git a/deal.II/source/lac/slepc_solver.cc b/deal.II/source/lac/slepc_solver.cc index b821a61c71..e436edf79e 100644 --- a/deal.II/source/lac/slepc_solver.cc +++ b/deal.II/source/lac/slepc_solver.cc @@ -531,13 +531,5 @@ namespace SLEPcWrappers DEAL_II_NAMESPACE_CLOSE -#else - -// On gcc2.95 on Alpha OSF1, the native assembler does not like empty -// files, so provide some dummy code -namespace -{ - void dummy () {} -} #endif // DEAL_II_WITH_SLEPC diff --git a/deal.II/source/lac/slepc_spectral_transformation.cc b/deal.II/source/lac/slepc_spectral_transformation.cc index ff64e5d87d..fdd6eb5ae7 100644 --- a/deal.II/source/lac/slepc_spectral_transformation.cc +++ b/deal.II/source/lac/slepc_spectral_transformation.cc @@ -164,12 +164,5 @@ namespace SLEPcWrappers DEAL_II_NAMESPACE_CLOSE -#else -// On gcc2.95 on Alpha OSF1, the native assembler does not like empty -// files, so provide some dummy code -namespace -{ - void dummy () {} -} #endif // DEAL_II_WITH_SLEPC diff --git a/deal.II/source/lac/sparsity_pattern.cc b/deal.II/source/lac/sparsity_pattern.cc index 18f2c1b0de..edef0ca4ef 100644 --- a/deal.II/source/lac/sparsity_pattern.cc +++ b/deal.II/source/lac/sparsity_pattern.cc @@ -1195,6 +1195,7 @@ template void SparsityPattern::copy_from (const template void SparsityPattern::copy_from (const FullMatrix &, bool); template void SparsityPattern::copy_from (const FullMatrix &, bool); +template void SparsityPattern::copy_from (const SparsityPattern &); template void SparsityPattern::copy_from (const CompressedSparsityPattern &); template void SparsityPattern::copy_from (const CompressedSetSparsityPattern &); template void SparsityPattern::copy_from (const CompressedSimpleSparsityPattern &); diff --git a/deal.II/source/lac/sparsity_tools.cc b/deal.II/source/lac/sparsity_tools.cc index f88015c32b..066aa09a9b 100644 --- a/deal.II/source/lac/sparsity_tools.cc +++ b/deal.II/source/lac/sparsity_tools.cc @@ -505,6 +505,132 @@ namespace SparsityTools MPI_Waitall(requests.size(), &requests[0], MPI_STATUSES_IGNORE); } + +template +void distribute_sparsity_pattern(CSP_t &csp, + const std::vector &owned_set_per_cpu, + const MPI_Comm &mpi_comm, + const IndexSet &myrange) +{ + size_type myid = Utilities::MPI::this_mpi_process(mpi_comm); + + typedef std::map > map_vec_t; + map_vec_t send_data; + + { + unsigned int dest_cpu=0; + + size_type n_local_rel_rows = myrange.n_elements(); + for (size_type row_idx=0; row_idx &dst = send_data[dest_cpu]; + + dst.push_back(rlen); // number of entries + dst.push_back(row); // row index + for (size_type c=0; c send_to; + send_to.reserve(send_data.size()); + for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it) + send_to.push_back(it->first); + + num_receive = + Utilities::MPI:: + compute_point_to_point_communication_pattern(mpi_comm, send_to).size(); + } + + std::vector requests(send_data.size()); + + + // send data + { + unsigned int idx=0; + for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx) + MPI_Isend(&(it->second[0]), + it->second.size(), + DEAL_II_DOF_INDEX_MPI_TYPE, + it->first, + 124, + mpi_comm, + &requests[idx]); + } + +//TODO: In the following, we read individual bytes and then reinterpret them +// as size_type objects. this is error prone. use properly typed reads that +// match the write above + { + //receive + std::vector recv_buf; + for (unsigned int index=0; index::const_iterator ptr = recv_buf.begin(); + std::vector::const_iterator end = recv_buf.end(); + while (ptr+1 +(BlockCompressedSimpleSparsityPattern &csp, + const std::vector &owned_set_per_cpu, + const MPI_Comm &mpi_comm, + const IndexSet &myrange); + #endif #undef SPARSITY_FUNCTIONS diff --git a/deal.II/source/lac/trilinos_block_vector.cc b/deal.II/source/lac/trilinos_block_vector.cc index b09660c236..7344ec1199 100644 --- a/deal.II/source/lac/trilinos_block_vector.cc +++ b/deal.II/source/lac/trilinos_block_vector.cc @@ -59,6 +59,11 @@ namespace TrilinosWrappers BlockVector & BlockVector::operator = (const BlockVector &v) { + // we only allow assignment to vectors with the same number of blocks + // or to an empty BlockVector + Assert (n_blocks() == 0 || n_blocks() == v.n_blocks(), + ExcDimensionMismatch(n_blocks(), v.n_blocks())); + if (this->n_blocks() != v.n_blocks()) reinit(v.n_blocks()); diff --git a/deal.II/source/lac/trilinos_precondition.cc b/deal.II/source/lac/trilinos_precondition.cc index d8342f04d2..a014bdd2f3 100644 --- a/deal.II/source/lac/trilinos_precondition.cc +++ b/deal.II/source/lac/trilinos_precondition.cc @@ -745,6 +745,52 @@ namespace TrilinosWrappers const AdditionalData &, const double, const ::dealii::SparsityPattern *); + + + + /* -------------------------- PreconditionAMG -------------------------- */ + + void + PreconditionIdentity::vmult(VectorBase &dst, + const VectorBase &src) const + { + dst = src; + } + + void + PreconditionIdentity::Tvmult(VectorBase &dst, + const VectorBase &src) const + { + dst = src; + } + + void + PreconditionIdentity::vmult(dealii::Vector &dst, + const dealii::Vector &src) const + { + dst = src; + } + + void + PreconditionIdentity::Tvmult(dealii::Vector &dst, + const dealii::Vector &src) const + { + dst = src; + } + + void + PreconditionIdentity::vmult(parallel::distributed::Vector &dst, + const parallel::distributed::Vector &src) const + { + dst = src; + } + + void + PreconditionIdentity::Tvmult(parallel::distributed::Vector &dst, + const parallel::distributed::Vector &src) const + { + dst = src; + } } DEAL_II_NAMESPACE_CLOSE diff --git a/deal.II/source/lac/trilinos_solver.cc b/deal.II/source/lac/trilinos_solver.cc index f04ca39f85..25edefb025 100644 --- a/deal.II/source/lac/trilinos_solver.cc +++ b/deal.II/source/lac/trilinos_solver.cc @@ -208,11 +208,17 @@ namespace TrilinosWrappers Assert (false, ExcNotImplemented()); } - // Introduce the - // preconditioner, ... - ierr = solver.SetPrecOperator (const_cast - (preconditioner.preconditioner.get())); - AssertThrow (ierr == 0, ExcTrilinosError(ierr)); + // Introduce the preconditioner, + // if the identity preconditioner is used, + // the precondioner is set to none, ... + if (preconditioner.preconditioner.use_count()!=0) + { + ierr = solver.SetPrecOperator (const_cast + (preconditioner.preconditioner.get())); + AssertThrow (ierr == 0, ExcTrilinosError(ierr)); + } + else + solver.SetAztecOption(AZ_precond,AZ_none); // ... set some options, ... solver.SetAztecOption (AZ_output, additional_data.output_solver_details ? diff --git a/deal.II/source/numerics/data_out.cc b/deal.II/source/numerics/data_out.cc index 51d7a560bc..79fd402ccb 100644 --- a/deal.II/source/numerics/data_out.cc +++ b/deal.II/source/numerics/data_out.cc @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -46,30 +47,263 @@ namespace internal namespace DataOut { template - template + ParallelDataBase:: + ParallelDataBase (const unsigned int n_datasets, + const unsigned int n_subdivisions, + const std::vector &n_postprocessor_outputs, + const Mapping &mapping, + const std::vector > > &finite_elements, + const UpdateFlags update_flags, + const bool use_face_values) + : + n_datasets (n_datasets), + n_subdivisions (n_subdivisions), + postprocessed_values (n_postprocessor_outputs.size()), + mapping_collection (mapping), + finite_elements (finite_elements), + update_flags (update_flags) + { + unsigned int n_q_points = 0; + if (use_face_values == false) + { + dealii::hp::QCollection + quadrature(QIterated(QTrapez<1>(), n_subdivisions)); + n_q_points = quadrature[0].size(); + x_fe_values.resize(this->finite_elements.size()); + for (unsigned int i=0; ifinite_elements.size(); ++i) + { + // check if there is a finite element that is equal to the + // present one, then we can re-use the FEValues object + for (unsigned int j=0; jfinite_elements[i].get() == + this->finite_elements[j].get()) + { + x_fe_values[i] = x_fe_values[j]; + break; + } + if (x_fe_values[i].get() == 0) + x_fe_values[i].reset(new dealii::hp::FEValues + (this->mapping_collection, + *this->finite_elements[i], + quadrature, + this->update_flags)); + } + } + else + { + dealii::hp::QCollection + quadrature(QIterated(QTrapez<1>(), n_subdivisions)); + n_q_points = quadrature[0].size(); + x_fe_face_values.resize(this->finite_elements.size()); + for (unsigned int i=0; ifinite_elements.size(); ++i) + { + // check if there is a finite element that is equal to the + // present one, then we can re-use the FEValues object + for (unsigned int j=0; jfinite_elements[i].get() == + this->finite_elements[j].get()) + { + x_fe_face_values[i] = x_fe_face_values[j]; + break; + } + if (x_fe_face_values[i].get() == 0) + x_fe_face_values[i].reset(new dealii::hp::FEFaceValues + (this->mapping_collection, + *this->finite_elements[i], + quadrature, + this->update_flags)); + } + } + + patch_values.resize (n_q_points); + patch_values_system.resize (n_q_points); + patch_gradients.resize (n_q_points); + patch_gradients_system.resize (n_q_points); + patch_hessians.resize (n_q_points); + patch_hessians_system.resize (n_q_points); + + for (unsigned int dataset=0; dataset(n_postprocessor_outputs[dataset])); + } + + + + + + // implement copy constructor to create a thread's own version of + // x_fe_values + template + ParallelDataBase:: + ParallelDataBase (const ParallelDataBase &data) + : + n_datasets (data.n_datasets), + n_subdivisions (data.n_subdivisions), + patch_values (data.patch_values), + patch_values_system (data.patch_values_system), + patch_gradients (data.patch_gradients), + patch_gradients_system (data.patch_gradients_system), + patch_hessians (data.patch_hessians), + patch_hessians_system (data.patch_hessians_system), + postprocessed_values (data.postprocessed_values), + mapping_collection (data.mapping_collection), + finite_elements (data.finite_elements), + update_flags (data.update_flags) + { + if (data.x_fe_values.empty() == false) + { + Assert(data.x_fe_face_values.empty() == true, ExcInternalError()); + dealii::hp::QCollection + quadrature(QIterated(QTrapez<1>(), n_subdivisions)); + x_fe_values.resize(this->finite_elements.size()); + for (unsigned int i=0; ifinite_elements.size(); ++i) + { + // check if there is a finite element that is equal to the + // present one, then we can re-use the FEValues object + for (unsigned int j=0; jfinite_elements[i].get() == + this->finite_elements[j].get()) + { + x_fe_values[i] = x_fe_values[j]; + break; + } + if (x_fe_values[i].get() == 0) + x_fe_values[i].reset(new dealii::hp::FEValues + (this->mapping_collection, + *this->finite_elements[i], + quadrature, + this->update_flags)); + } + } + else + { + dealii::hp::QCollection + quadrature(QIterated(QTrapez<1>(), n_subdivisions)); + x_fe_face_values.resize(this->finite_elements.size()); + for (unsigned int i=0; ifinite_elements.size(); ++i) + { + // check if there is a finite element that is equal to the + // present one, then we can re-use the FEValues object + for (unsigned int j=0; jfinite_elements[i].get() == + this->finite_elements[j].get()) + { + x_fe_face_values[i] = x_fe_face_values[j]; + break; + } + if (x_fe_face_values[i].get() == 0) + x_fe_face_values[i].reset(new dealii::hp::FEFaceValues + (this->mapping_collection, + *this->finite_elements[i], + quadrature, + this->update_flags)); + } + } + } + + + + template + template + void + ParallelDataBase:: + reinit_all_fe_values(std::vector > > &dof_data, + const typename dealii::Triangulation::cell_iterator &cell, + const unsigned int face) + { + for (unsigned int dataset=0; datasetget_triangulation(), + cell->level(), + cell->index(), + dof_data[dataset]->dof_handler); + if (x_fe_values.empty()) + { + AssertIndexRange(face, + GeometryInfo::faces_per_cell); + x_fe_face_values[dataset]->reinit(dh_cell, face); + } + else + x_fe_values[dataset]->reinit (dh_cell); + } + } + if (dof_data.empty()) + { + if (x_fe_values.empty()) + { + AssertIndexRange(face, + GeometryInfo::faces_per_cell); + x_fe_face_values[0]->reinit(cell, face); + } + else + x_fe_values[0]->reinit (cell); + } + } + + + + template + const FEValuesBase & + ParallelDataBase:: + get_present_fe_values(const unsigned int dataset) const + { + AssertIndexRange(dataset, finite_elements.size()); + if (x_fe_values.empty()) + return x_fe_face_values[dataset]->get_present_fe_values(); + else + return x_fe_values[dataset]->get_present_fe_values(); + } + + + + template + void + ParallelDataBase:: + resize_system_vectors(const unsigned int n_components) + { + Assert(patch_values_system.size() > 0, ExcInternalError()); + AssertDimension(patch_values_system.size(), + patch_gradients_system.size()); + AssertDimension(patch_values_system.size(), + patch_hessians_system.size()); + if (patch_values_system[0].size() == n_components) + return; + for (unsigned int k=0; k ParallelData:: - ParallelData (const Quadrature &quadrature, - const unsigned int n_components, - const unsigned int n_datasets, + ParallelData (const unsigned int n_datasets, const unsigned int n_subdivisions, const std::vector &n_postprocessor_outputs, const Mapping &mapping, - const std::vector > &cell_to_patch_index_map, - const FE &finite_elements, - const UpdateFlags update_flags) + const std::vector > > &finite_elements, + const UpdateFlags update_flags, + const std::vector > &cell_to_patch_index_map) : - ParallelDataBase (n_components, - n_datasets, + ParallelDataBase (n_datasets, n_subdivisions, - quadrature.size(), n_postprocessor_outputs, - finite_elements), - q_collection (quadrature), - mapping_collection (mapping), - x_fe_values (this->mapping_collection, - this->fe_collection, - q_collection, - update_flags), + mapping, + finite_elements, + update_flags, + false), cell_to_patch_index_map (&cell_to_patch_index_map) {} @@ -77,10 +311,8 @@ namespace internal /** - * In a WorkStream context, use - * this function to append the - * patch computed by the parallel - * stage to the array of patches. + * In a WorkStream context, use this function to append the patch computed + * by the parallel stage to the array of patches. */ template void @@ -99,9 +331,11 @@ namespace internal namespace DataOut { template - DataEntryBase::DataEntryBase (const std::vector &names_in, + DataEntryBase::DataEntryBase (const DH *dofs, + const std::vector &names_in, const std::vector &data_component_interpretation) : + dof_handler (dofs, typeid(dealii::DataOut_DoFData).name()), names(names_in), data_component_interpretation (data_component_interpretation), postprocessor(0, typeid(*this).name()), @@ -111,9 +345,7 @@ namespace internal ExcDimensionMismatch(data_component_interpretation.size(), names.size())); - // check that the names use only allowed - // characters - // check names for invalid characters + // check that the names use only allowed characters for (unsigned int i=0; i - DataEntryBase::DataEntryBase (const DataPostprocessor *data_postprocessor) + DataEntryBase::DataEntryBase (const DH *dofs, + const DataPostprocessor *data_postprocessor) : + dof_handler (dofs, typeid(dealii::DataOut_DoFData).name()), names(data_postprocessor->get_names()), data_component_interpretation (data_postprocessor->get_data_component_interpretation()), postprocessor(data_postprocessor, typeid(*this).name()), @@ -141,8 +375,7 @@ namespace internal ExcDimensionMismatch (data_postprocessor->get_names().size(), data_postprocessor->get_data_component_interpretation().size())); - // check that the names use only allowed - // characters + // check that the names use only allowed characters for (unsigned int i=0; i &names, const std::vector &data_component_interpretation); /** - * Constructor when a data - * postprocessor is going to be - * used. In that case, the names and - * vector declarations are going to - * be acquired from the postprocessor. + * Constructor when a data postprocessor is going to be used. In that + * case, the names and vector declarations are going to be acquired from + * the postprocessor. */ - DataEntry (const VectorType *data, + DataEntry (const DH *dofs, + const VectorType *data, const DataPostprocessor *data_postprocessor); /** - * Assuming that the stored vector is - * a cell vector, extract the given + * Assuming that the stored vector is a cell vector, extract the given * element from it. */ virtual @@ -207,10 +433,8 @@ namespace internal get_cell_data_value (const unsigned int cell_number) const; /** - * Given a FEValuesBase object, - * extract the values on the present - * cell from the vector we actually - * store. + * Given a FEValuesBase object, extract the values on the present cell + * from the vector we actually store. */ virtual void @@ -218,12 +442,9 @@ namespace internal std::vector &patch_values) const; /** - * Given a FEValuesBase object, - * extract the values on the present - * cell from the vector we actually - * store. This function does the same - * as the one above but for - * vector-valued finite elements. + * Given a FEValuesBase object, extract the values on the present cell + * from the vector we actually store. This function does the same as the + * one above but for vector-valued finite elements. */ virtual void @@ -231,10 +452,8 @@ namespace internal std::vector > &patch_values_system) const; /** - * Given a FEValuesBase object, - * extract the gradients on the present - * cell from the vector we actually - * store. + * Given a FEValuesBase object, extract the gradients on the present + * cell from the vector we actually store. */ virtual void @@ -242,12 +461,9 @@ namespace internal std::vector > &patch_gradients) const; /** - * Given a FEValuesBase object, - * extract the gradients on the present - * cell from the vector we actually - * store. This function does the same - * as the one above but for - * vector-valued finite elements. + * Given a FEValuesBase object, extract the gradients on the present + * cell from the vector we actually store. This function does the same + * as the one above but for vector-valued finite elements. */ virtual void @@ -255,10 +471,8 @@ namespace internal std::vector > > &patch_gradients_system) const; /** - * Given a FEValuesBase object, extract - * the second derivatives on the - * present cell from the vector we - * actually store. + * Given a FEValuesBase object, extract the second derivatives on the + * present cell from the vector we actually store. */ virtual void @@ -266,12 +480,9 @@ namespace internal std::vector > &patch_hessians) const; /** - * Given a FEValuesBase object, extract - * the second derivatives on the - * present cell from the vector we - * actually store. This function does - * the same as the one above but for - * vector-valued finite elements. + * Given a FEValuesBase object, extract the second derivatives on the + * present cell from the vector we actually store. This function does + * the same as the one above but for vector-valued finite elements. */ virtual void @@ -279,25 +490,20 @@ namespace internal std::vector > > &patch_hessians_system) const; /** - * Clear all references to the - * vectors. + * Clear all references to the vectors. */ virtual void clear (); /** - * Determine an estimate for - * the memory consumption (in - * bytes) of this object. + * Determine an estimate for the memory consumption (in bytes) of this + * object. */ virtual std::size_t memory_consumption () const; private: /** - * Pointer to the data - * vector. Note that - * ownership of the vector - * pointed to remains with - * the caller of this class. + * Pointer to the data vector. Note that ownership of the vector pointed + * to remains with the caller of this class. */ const VectorType *vector; }; @@ -306,11 +512,12 @@ namespace internal template DataEntry:: - DataEntry (const VectorType *data, + DataEntry (const DH *dofs, + const VectorType *data, const std::vector &names, const std::vector &data_component_interpretation) : - DataEntryBase (names, data_component_interpretation), + DataEntryBase (dofs, names, data_component_interpretation), vector (data) {} @@ -318,10 +525,11 @@ namespace internal template DataEntry:: - DataEntry (const VectorType *data, + DataEntry (const DH *dofs, + const VectorType *data, const DataPostprocessor *data_postprocessor) : - DataEntryBase (data_postprocessor), + DataEntryBase (dofs, data_postprocessor), vector (data) {} @@ -438,6 +646,7 @@ namespace internal DataEntry::clear () { vector = 0; + this->dof_handler = 0; } } } @@ -448,6 +657,7 @@ template DataOut_DoFData::DataOut_DoFData () : + triangulation(0,typeid(*this).name()), dofs(0,typeid(*this).name()) {} @@ -469,7 +679,21 @@ attach_dof_handler (const DH &d) Assert (dof_data.size() == 0, ExcOldDataStillPresent()); Assert (cell_data.size() == 0, ExcOldDataStillPresent()); - dofs = &d; + triangulation = SmartPointer >(&d.get_tria(), typeid(*this).name()); + dofs = SmartPointer(&d, typeid(*this).name()); +} + + + +template +void +DataOut_DoFData:: +attach_triangulation (const Triangulation &tria) +{ + Assert (dof_data.size() == 0, ExcOldDataStillPresent()); + Assert (cell_data.size() == 0, ExcOldDataStillPresent()); + + triangulation = SmartPointer >(&tria, typeid(*this).name()); } @@ -485,21 +709,19 @@ add_data_vector (const VECTOR &vec, const DataVectorType type, const std::vector &data_component_interpretation) { - Assert (dofs != 0, ExcNoDoFHandlerSelected ()); - const unsigned int n_components = dofs->get_fe().n_components (); + Assert (triangulation != 0, ExcNoTriangulationSelected ()); + const unsigned int n_components = + dofs != 0 ? dofs->get_fe().n_components () : 1; std::vector names; - // if only one component or vector - // is cell vector: we only need one - // name + // if only one component or vector is cell vector: we only need one name if ((n_components == 1) || - (vec.size() == dofs->get_tria().n_active_cells())) + (vec.size() == triangulation->n_active_cells())) { names.resize (1, name); } else - // otherwise append _i to the - // given name + // otherwise append _i to the given name { names.resize (n_components); for (unsigned int i=0; i &data_component_interpretation_) { - Assert (dofs != 0, ExcNoDoFHandlerSelected ()); + Assert (triangulation != 0, ExcNoTriangulationSelected ()); const std::vector & data_component_interpretation @@ -541,7 +763,7 @@ add_data_vector (const VECTOR &vec, DataVectorType actual_type = type; if (type == type_automatic) { - if (vec.size() == dofs->get_tria().n_active_cells()) + if (vec.size() == triangulation->n_active_cells()) actual_type = type_cell_data; else actual_type = type_dof_data; @@ -550,31 +772,30 @@ add_data_vector (const VECTOR &vec, switch (actual_type) { case type_cell_data: - Assert (vec.size() == dofs->get_tria().n_active_cells(), - ExcInvalidVectorSize (vec.size(), - dofs->n_dofs(), - dofs->get_tria().n_active_cells())); + Assert (vec.size() == triangulation->n_active_cells(), + ExcDimensionMismatch (vec.size(), + triangulation->n_active_cells())); Assert (names.size() == 1, ExcInvalidNumberOfNames (names.size(), 1)); break; case type_dof_data: + Assert (dofs != 0, ExcNoDoFHandlerSelected ()); Assert (vec.size() == dofs->n_dofs(), ExcInvalidVectorSize (vec.size(), dofs->n_dofs(), - dofs->get_tria().n_active_cells())); + triangulation->n_active_cells())); Assert (names.size() == dofs->get_fe().n_components(), ExcInvalidNumberOfNames (names.size(), dofs->get_fe().n_components())); break; case type_automatic: - // this case should have - // been handled above... + // this case should have been handled above... Assert (false, ExcInternalError()); } internal::DataOut::DataEntryBase *new_entry - = new internal::DataOut::DataEntry(&vec, names, + = new internal::DataOut::DataEntry(dofs, &vec, names, data_component_interpretation); if (actual_type == type_dof_data) dof_data.push_back (std_cxx1x::shared_ptr >(new_entry)); @@ -592,13 +813,10 @@ DataOut_DoFData:: add_data_vector (const VECTOR &vec, const DataPostprocessor &data_postprocessor) { - // this is a specialized version of the - // other function where we have a - // postprocessor. if we do, we know that we - // have type_dof_data, which makes things a - // bit simpler, we also don't need to deal - // with some of the other stuff and use a - // different constructor of DataEntry + // this is a specialized version of the other function where we have a + // postprocessor. if we do, we know that we have type_dof_data, which makes + // things a bit simpler, we also don't need to deal with some of the other + // stuff and use a different constructor of DataEntry Assert (dofs != 0, ExcNoDoFHandlerSelected ()); @@ -608,7 +826,103 @@ add_data_vector (const VECTOR &vec, dofs->get_tria().n_active_cells())); internal::DataOut::DataEntryBase *new_entry - = new internal::DataOut::DataEntry(&vec, &data_postprocessor); + = new internal::DataOut::DataEntry(dofs, &vec, &data_postprocessor); + dof_data.push_back (std_cxx1x::shared_ptr >(new_entry)); +} + + + +template +template +void +DataOut_DoFData:: +add_data_vector (const DH &dof_handler, + const VECTOR &vec, + const DataPostprocessor &data_postprocessor) +{ + // this is a specialized version of the other function where we have a + // postprocessor. if we do, we know that we have type_dof_data, which makes + // things a bit simpler, we also don't need to deal with some of the other + // stuff and use a different constructor of DataEntry + + AssertDimension (vec.size(), dof_handler.n_dofs()); + + internal::DataOut::DataEntryBase *new_entry + = new internal::DataOut::DataEntry(&dof_handler, &vec, &data_postprocessor); + dof_data.push_back (std_cxx1x::shared_ptr >(new_entry)); +} + + + +template +template +void +DataOut_DoFData:: +add_data_vector (const DH &dof_handler, + const VECTOR &data, + const std::string &name, + const std::vector &data_component_interpretation) +{ + const unsigned int n_components = dof_handler.get_fe().n_components (); + + std::vector names; + // if only one component: we only need one name + if (n_components == 1) + names.resize (1, name); + else + // otherwise append _i to the given name + { + names.resize (n_components); + for (unsigned int i=0; i +template +void +DataOut_DoFData:: +add_data_vector (const DH &dof_handler, + const VECTOR &data, + const std::vector &names, + const std::vector &data_component_interpretation_) +{ + // this is an extended version of the other functions where we pass a vector + // together with its DoFHandler. if we do, we know that we have + // type_dof_data, which makes things a bit simpler + if (triangulation == 0) + triangulation = SmartPointer >(&dof_handler.get_tria(), typeid(*this).name()); + + Assert (&dof_handler.get_tria() == triangulation, + ExcMessage("The triangulation attached to the DoFHandler does not " + "match with the one set previously")); + + Assert (data.size() == dof_handler.n_dofs(), + ExcDimensionMismatch (data.size(), dof_handler.n_dofs())); + + const std::vector & + data_component_interpretation + = (data_component_interpretation_.size() != 0 + ? + data_component_interpretation_ + : + std::vector + (names.size(), DataComponentInterpretation::component_is_scalar)); + + internal::DataOut::DataEntryBase *new_entry + = new internal::DataOut::DataEntry(&dof_handler, &data, names, + data_component_interpretation); dof_data.push_back (std_cxx1x::shared_ptr >(new_entry)); } @@ -796,6 +1110,47 @@ DataOut_DoFData::get_patches () const +template +std::vector > > +DataOut_DoFData::get_finite_elements() const +{ + const unsigned int dhdim = DH::dimension; + const unsigned int dhspacedim = DH::space_dimension; + std::vector > > + finite_elements(this->dof_data.size()); + for (unsigned int i=0; idof_data.size(); ++i) + { + Assert (dof_data[i]->dof_handler != 0, ExcNoDoFHandlerSelected ()); + + // avoid creating too many finite elements and doing a lot of work on + // initializing FEValues downstream: if two DoFHandlers are the same + // (checked by pointer comparison), we can re-use the shared_ptr object + // for the second one. We cannot check for finite element equalities + // because we need different FEValues objects for different dof + // handlers. + bool duplicate = false; + for (unsigned int j=0; jdof_handler == dof_data[j]->dof_handler) + { + finite_elements[i] = finite_elements[j]; + duplicate = true; + } + if (duplicate == false) + finite_elements[i].reset(new dealii::hp::FECollection + (this->dof_data[i]->dof_handler->get_fe())); + } + if (this->dof_data.empty()) + { + finite_elements.resize(1); + finite_elements[0].reset(new dealii::hp::FECollection + (FE_DGQ(0))); + } + return finite_elements; +} + + + template std::size_t @@ -819,13 +1174,10 @@ build_one_patch (const std::pair *cell_and_index, DataOutBase::Patch &patch, const CurvedCellRegion curved_cell_region) { - // use ucd_to_deal map as patch vertices - // are in the old, unnatural ordering. if - // the mapping does not preserve locations - // (e.g. MappingQEulerian), we need to - // compute the offset of the vertex for the - // graphical output. Otherwise, we can just - // use the vertex info. + // use ucd_to_deal map as patch vertices are in the old, unnatural + // ordering. if the mapping does not preserve locations + // (e.g. MappingQEulerian), we need to compute the offset of the vertex for + // the graphical output. Otherwise, we can just use the vertex info. for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) if (data.mapping_collection[0].preserves_vertex_locations()) patch.vertices[vertex] = cell_and_index->first->vertex(vertex); @@ -836,25 +1188,21 @@ build_one_patch (const std::pair *cell_and_index, if (data.n_datasets > 0) { - data.x_fe_values.reinit (cell_and_index->first); - const FEValues &fe_patch_values - = data.x_fe_values.get_present_fe_values (); + // create DH::active_cell_iterator and initialize FEValues + data.reinit_all_fe_values(this->dof_data, cell_and_index->first); + + const FEValuesBase &fe_patch_values + = data.get_present_fe_values (0); const unsigned int n_q_points = fe_patch_values.n_quadrature_points; - // depending on the requested output - // of curved cells, if necessary - // append the quadrature points to - // the last rows of the patch.data - // member. This is the case if we - // want to produce curved cells at - // the boundary and this cell - // actually is at the boundary, or - // else if we want to produce curved - // cells everywhere + // depending on the requested output of curved cells, if necessary + // append the quadrature points to the last rows of the patch.data + // member. This is the case if we want to produce curved cells at the + // boundary and this cell actually is at the boundary, or else if we + // want to produce curved cells everywhere // - // note: a cell is *always* at - // the boundary if dim *cell_and_index, { Assert(patch.space_dim==DH::space_dimension, ExcInternalError()); const std::vector > &q_points=fe_patch_values.get_quadrature_points(); - // resize the patch.data member - // in order to have enough memory - // for the quadrature points as - // well + // resize the patch.data member in order to have enough memory for + // the quadrature points as well patch.data.reinit (data.n_datasets+DH::space_dimension, n_q_points); - // set the flag indicating that - // for this cell the points are + // set the flag indicating that for this cell the points are // explicitly given patch.points_are_available=true; // copy points to patch.data @@ -892,19 +1237,22 @@ build_one_patch (const std::pair *cell_and_index, // first fill dof_data for (unsigned int dataset=0; datasetdof_data.size(); ++dataset) { + const FEValuesBase &fe_patch_values + = data.get_present_fe_values (dataset); + const unsigned int n_components = + fe_patch_values.get_fe().n_components(); + const DataPostprocessor *postprocessor=this->dof_data[dataset]->postprocessor; if (postprocessor != 0) { - // we have to postprocess the - // data, so determine, which - // fields have to be updated + // we have to postprocess the data, so determine, which fields + // have to be updated const UpdateFlags update_flags=postprocessor->get_needed_update_flags(); - if (data.n_components == 1) + if (n_components == 1) { - // at each point there is - // only one component of - // value, gradient etc. + // at each point there is only one component of value, + // gradient etc. if (update_flags & update_values) this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values); @@ -930,9 +1278,9 @@ build_one_patch (const std::pair *cell_and_index, } else { - // at each point there is - // a vector valued - // function and its + data.resize_system_vectors (n_components); + + // at each point there is a vector valued function and its // derivative... if (update_flags & update_values) this->dof_data[dataset]->get_function_values (fe_patch_values, @@ -966,13 +1314,10 @@ build_one_patch (const std::pair *cell_and_index, = data.postprocessed_values[dataset][q](component); } else - // now we use the given data - // vector without - // modifications. again, we - // treat single component - // functions separately for - // efficiency reasons. - if (data.n_components == 1) + // now we use the given data vector without modifications. again, + // we treat single component functions separately for efficiency + // reasons. + if (n_components == 1) { this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values); @@ -981,25 +1326,22 @@ build_one_patch (const std::pair *cell_and_index, } else { + data.resize_system_vectors(n_components); this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values_system); - for (unsigned int component=0; componentdof_data[dataset]->n_output_variables; } - // then do the cell data. only - // compute the number of a cell if - // needed; also make sure that we - // only access cell data if the - // first_cell/next_cell functions - // only return active cells + // then do the cell data. only compute the number of a cell if needed; + // also make sure that we only access cell data if the + // first_cell/next_cell functions only return active cells if (this->cell_data.size() != 0) { Assert (!cell_and_index->first->has_children(), ExcNotImplemented()); @@ -1017,32 +1359,15 @@ build_one_patch (const std::pair *cell_and_index, for (unsigned int f=0; f::faces_per_cell; ++f) { - // let's look up whether - // the neighbor behind that - // face is noted in the - // table of cells which we - // treat. this can only - // happen if the neighbor - // exists, and is on the - // same level as this cell, - // but it may also happen - // that the neighbor is not - // a member of the range of - // cells over which we - // loop, in which case the - // respective entry in the - // cell_to_patch_index_map - // will have the value - // no_neighbor. (note that - // since we allocated only - // as much space in this - // array as the maximum - // index of the cells we - // loop over, not every - // neighbor may have its - // space in it, so we have - // to assume that it is - // extended by values + // let's look up whether the neighbor behind that face is noted in the + // table of cells which we treat. this can only happen if the neighbor + // exists, and is on the same level as this cell, but it may also happen + // that the neighbor is not a member of the range of cells over which we + // loop, in which case the respective entry in the + // cell_to_patch_index_map will have the value no_neighbor. (note that + // since we allocated only as much space in this array as the maximum + // index of the cells we loop over, not every neighbor may have its + // space in it, so we have to assume that it is extended by values // no_neighbor) if (cell_and_index->first->at_boundary(f) || @@ -1067,10 +1392,8 @@ build_one_patch (const std::pair *cell_and_index, continue; } - // now, there is a - // neighbor, so get its - // patch number and set it - // for the neighbor index + // now, there is a neighbor, so get its patch number and set it for the + // neighbor index patch.neighbors[f] = (*data.cell_to_patch_index_map)[neighbor->level()][neighbor->index()]; } @@ -1086,17 +1409,18 @@ void DataOut::build_patches (const unsigned int n_subdivisions) } + template void DataOut::build_patches (const Mapping &mapping, const unsigned int nnnn_subdivisions, const CurvedCellRegion curved_region) { - // Check consistency of redundant - // template parameter + // Check consistency of redundant template parameter Assert (dim==DH::dimension, ExcDimensionMismatch(dim, DH::dimension)); typedef DataOut_DoFData BaseClass; - Assert (this->dofs != 0, typename BaseClass::ExcNoDoFHandlerSelected()); + Assert (this->triangulation != 0, + typename BaseClass::ExcNoTriangulationSelected()); const unsigned int n_subdivisions = (nnnn_subdivisions != 0) ? nnnn_subdivisions @@ -1104,19 +1428,15 @@ void DataOut::build_patches (const Mapping= 1, ExcInvalidNumberOfSubdivisions(n_subdivisions)); - // first count the cells we want to - // create patches of. also fill the - // object that maps the cell - // indices to the patch numbers, as - // this will be needed for - // generation of neighborship - // information + // first count the cells we want to create patches of. also fill the object + // that maps the cell indices to the patch numbers, as this will be needed + // for generation of neighborship information std::vector > cell_to_patch_index_map; - cell_to_patch_index_map.resize (this->dofs->get_tria().n_levels()); - for (unsigned int l=0; ldofs->get_tria().n_levels(); ++l) + cell_to_patch_index_map.resize (this->triangulation->n_levels()); + for (unsigned int l=0; ltriangulation->n_levels(); ++l) { unsigned int max_index = 0; - for (cell_iterator cell=first_locally_owned_cell(); cell != this->dofs->end(); + for (cell_iterator cell=first_locally_owned_cell(); cell != this->triangulation->end(); cell = next_locally_owned_cell(cell)) if (static_cast(cell->level()) == l) max_index = std::max (max_index, @@ -1128,24 +1448,19 @@ void DataOut::build_patches (const Mapping > all_cells; { - // set the index of the first - // cell. if - // first_locally_owned_cell / - // next_locally_owned_cell - // returns non-active cells, then - // the index is not usable - // anyway, but otherwise we - // should keep track where we are + // set the index of the first cell. if first_locally_owned_cell / + // next_locally_owned_cell returns non-active cells, then the index is not + // usable anyway, but otherwise we should keep track where we are unsigned int index; - if ((first_locally_owned_cell() == this->dofs->end()) + cell_iterator cell = first_locally_owned_cell(); + if ((cell == this->triangulation->end()) || - (first_locally_owned_cell()->has_children())) + (cell->has_children())) index = 0; else - index = std::distance (this->dofs->begin_active(), - active_cell_iterator(first_locally_owned_cell())); - for (cell_iterator cell=first_locally_owned_cell(); cell != this->dofs->end(); - cell = next_locally_owned_cell(cell)) + index = std::distance (this->triangulation->begin_active(), + active_cell_iterator(cell)); + for ( ; cell != this->triangulation->end(); ) { Assert (static_cast(cell->level()) < cell_to_patch_index_map.size(), @@ -1158,22 +1473,18 @@ void DataOut::build_patches (const Mappinghas_children() && - next_locally_owned_cell(cell) != this->dofs->end() && - !next_locally_owned_cell(cell)->has_children()) + next != this->triangulation->end() && + !next->has_children()) index += std::distance (active_cell_iterator(cell), - active_cell_iterator(next_locally_owned_cell(cell))); + active_cell_iterator(next)); + cell = next; } } @@ -1181,13 +1492,7 @@ void DataOut::build_patches (const Mappingpatches.reserve (all_cells.size()); Assert (this->patches.size() == 0, ExcInternalError()); - // now create a default patch and a - // default object for the - // WorkStream object to work with - const QTrapez<1> q_trapez; - const QIterated patch_points (q_trapez, n_subdivisions); - - const unsigned int n_components = this->dofs->get_fe().n_components(); + // now create a default object for the WorkStream object to work with unsigned int n_datasets=this->cell_data.size(); for (unsigned int i=0; idof_data.size(); ++i) n_datasets += this->dof_data[i]->n_output_variables; @@ -1209,26 +1514,24 @@ void DataOut::build_patches (const Mappingdof_data.size(); ++i) if (this->dof_data[i]->postprocessor) update_flags |= this->dof_data[i]->postprocessor->get_needed_update_flags(); - // perhaps update_normal_vectors is present, - // which would only be useful on faces, but - // we may not use it here. + // perhaps update_normal_vectors is present, which would only be useful on + // faces, but we may not use it here. Assert (!(update_flags & update_normal_vectors), ExcMessage("The update of normal vectors may not be requested for evaluation of " "data on cells via DataPostprocessor.")); internal::DataOut::ParallelData - thread_data (patch_points, - n_components, n_datasets, n_subdivisions, + thread_data (n_datasets, n_subdivisions, n_postprocessor_outputs, mapping, - cell_to_patch_index_map, - this->dofs->get_fe(), - update_flags); + this->get_finite_elements(), + update_flags, + cell_to_patch_index_map); ::dealii::DataOutBase::Patch sample_patch; sample_patch.n_subdivisions = n_subdivisions; - sample_patch.data.reinit (n_datasets, patch_points.size()); - + sample_patch.data.reinit (n_datasets, + Utilities::fixed_power(n_subdivisions+1)); // now build the patches in parallel @@ -1250,7 +1553,7 @@ template typename DataOut::cell_iterator DataOut::first_cell () { - return this->dofs->begin_active (); + return this->triangulation->begin_active (); } @@ -1259,10 +1562,10 @@ template typename DataOut::cell_iterator DataOut::next_cell (const typename DataOut::cell_iterator &cell) { - // convert the iterator to an - // active_iterator and advance - // this to the next active cell - typename DH::active_cell_iterator active_cell = cell; + // convert the iterator to an active_iterator and advance this to the next + // active cell + typename Triangulation:: + active_cell_iterator active_cell = cell; ++active_cell; return active_cell; } @@ -1274,12 +1577,11 @@ typename DataOut::cell_iterator DataOut::first_locally_owned_cell () { typename DataOut::cell_iterator - cell = this->dofs->begin_active (); + cell = this->triangulation->begin_active (); - // skip cells if the current one - // has no children (is active) and - // is a ghost or artificial cell - while ((cell != this->dofs->end()) && + // skip cells if the current one has no children (is active) and is a ghost + // or artificial cell + while ((cell != this->triangulation->end()) && (cell->has_children() == false) && !cell->is_locally_owned()) cell = next_cell(cell); @@ -1295,7 +1597,7 @@ DataOut::next_locally_owned_cell (const typename DataOut::cell_i { typename DataOut::cell_iterator cell = next_cell(old_cell); - while ((cell != this->dofs->end()) && + while ((cell != this->triangulation->end()) && (cell->has_children() == false) && !cell->is_locally_owned()) cell = next_cell(cell); diff --git a/deal.II/source/numerics/data_out.inst.in b/deal.II/source/numerics/data_out.inst.in index 55fc701433..aa157920a1 100644 --- a/deal.II/source/numerics/data_out.inst.in +++ b/deal.II/source/numerics/data_out.inst.in @@ -38,6 +38,28 @@ for (VEC : SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENS add_data_vector (const VEC &, const DataPostprocessor::space_dimension> &); + template void + DataOut_DoFData,deal_II_dimension,deal_II_dimension>:: + add_data_vector (const DH &, + const VEC &, + const std::string &, + const std::vector &); + + template void + DataOut_DoFData,deal_II_dimension,deal_II_dimension>:: + add_data_vector (const DH &, + const VEC &, + const std::vector &, + const std::vector &); + + template void + DataOut_DoFData,deal_II_dimension,deal_II_dimension>:: + add_data_vector (const DH &, + const VEC &, + const DataPostprocessor::space_dimension> &); + + + // stuff needed for face data template void @@ -59,6 +81,28 @@ for (VEC : SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENS add_data_vector (const VEC &, const DataPostprocessor::space_dimension> &); + template void + DataOut_DoFData,deal_II_dimension-1,deal_II_dimension>:: + add_data_vector (const DH &, + const VEC &, + const std::string &, + const std::vector &); + + template void + DataOut_DoFData,deal_II_dimension-1,deal_II_dimension>:: + add_data_vector (const DH &, + const VEC &, + const std::vector &, + const std::vector &); + + template void + DataOut_DoFData,deal_II_dimension-1,deal_II_dimension>:: + add_data_vector (const DH &, + const VEC &, + const DataPostprocessor::space_dimension> &); + + + // things for DataOutRotation template void @@ -80,6 +124,28 @@ for (VEC : SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENS add_data_vector (const VEC &, const DataPostprocessor::space_dimension> &); + template void + DataOut_DoFData,deal_II_dimension+1,deal_II_dimension+1>:: + add_data_vector (const DH &, + const VEC &, + const std::string &, + const std::vector &); + + template void + DataOut_DoFData,deal_II_dimension+1,deal_II_dimension+1>:: + add_data_vector (const DH &, + const VEC &, + const std::vector &, + const std::vector &); + + template void + DataOut_DoFData,deal_II_dimension+1,deal_II_dimension+1>:: + add_data_vector (const DH &, + const VEC &, + const DataPostprocessor::space_dimension> &); + + + // codim 1 #if deal_II_dimension < 3 @@ -101,6 +167,26 @@ for (VEC : SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENS DataOut_DoFData,deal_II_dimension,deal_II_dimension+1>:: add_data_vector (const VEC &, const DataPostprocessor::space_dimension> &); + + template void + DataOut_DoFData,deal_II_dimension,deal_II_dimension+1>:: + add_data_vector (const DH &, + const VEC &, + const std::string &, + const std::vector &); + + template void + DataOut_DoFData,deal_II_dimension,deal_II_dimension+1>:: + add_data_vector (const DH &, + const VEC &, + const std::vector &, + const std::vector &); + + template void + DataOut_DoFData,deal_II_dimension,deal_II_dimension+1>:: + add_data_vector (const DH &, + const VEC &, + const DataPostprocessor::space_dimension> &); #endif @@ -126,6 +212,26 @@ for (VEC : SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENS DataOut_DoFData,1,3>:: add_data_vector (const VEC &, const DataPostprocessor::space_dimension> &); + + template void + DataOut_DoFData,1,3>:: + add_data_vector (const DH<1,3> &, + const VEC &, + const std::string &, + const std::vector &); + + template void + DataOut_DoFData,1,3>:: + add_data_vector (const DH<1,3> &, + const VEC &, + const std::vector &, + const std::vector &); + + template void + DataOut_DoFData,1,3>:: + add_data_vector (const DH<1,3> &, + const VEC &, + const DataPostprocessor::space_dimension> &); #endif } @@ -250,3 +356,34 @@ for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS) #endif } + + +for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS) +{ + namespace internal \{ + namespace DataOut \{ +#if deal_II_dimension <= deal_II_space_dimension + template struct ParallelDataBase; + template struct ParallelData; +#endif + \} + \} +} + + +for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS) +{ + namespace internal \{ + namespace DataOut \{ +#if deal_II_dimension <= deal_II_space_dimension + template + void + ParallelDataBase:: + reinit_all_fe_values > + (std::vector > > > &dof_data, + const dealii::Triangulation::cell_iterator &cell, + const unsigned int face); +#endif + \} + \} +} diff --git a/deal.II/source/numerics/data_out_faces.cc b/deal.II/source/numerics/data_out_faces.cc index 9d282370ae..4dd1ccec43 100644 --- a/deal.II/source/numerics/data_out_faces.cc +++ b/deal.II/source/numerics/data_out_faces.cc @@ -36,38 +36,29 @@ namespace internal namespace DataOutFaces { template - template ParallelData:: - ParallelData (const Quadrature &quadrature, - const unsigned int n_components, - const unsigned int n_datasets, + ParallelData (const unsigned int n_datasets, const unsigned int n_subdivisions, const std::vector &n_postprocessor_outputs, const Mapping &mapping, - const FE &finite_elements, + const std::vector > > &finite_elements, const UpdateFlags update_flags) : internal::DataOut:: - ParallelDataBase (n_components, - n_datasets, + ParallelDataBase (n_datasets, n_subdivisions, - quadrature.size(), n_postprocessor_outputs, - finite_elements), - q_collection (quadrature), - mapping_collection (mapping), - x_fe_values (this->mapping_collection, - this->fe_collection, - q_collection, - update_flags) + mapping, + finite_elements, + update_flags, + true) {} + /** - * In a WorkStream context, use - * this function to append the - * patch computed by the parallel - * stage to the array of patches. + * In a WorkStream context, use this function to append the patch computed + * by the parallel stage to the array of patches. */ template void @@ -81,6 +72,7 @@ namespace internal } + template DataOutFaces::DataOutFaces(const bool so) : @@ -88,6 +80,7 @@ DataOutFaces::DataOutFaces(const bool so) {} + template void DataOutFaces:: @@ -98,14 +91,10 @@ build_one_patch (const FaceDescriptor *cell_and_face, Assert (cell_and_face->first->is_locally_owned(), ExcNotImplemented()); - // we use the mapping to transform the - // vertices. However, the mapping works on - // cells, not faces, so transform the face - // vertex to a cell vertex, that to a unit - // cell vertex and then, finally, that to - // the mapped vertex. In most cases this - // complicated procedure will be the - // identity. + // we use the mapping to transform the vertices. However, the mapping works + // on cells, not faces, so transform the face vertex to a cell vertex, that + // to a unit cell vertex and then, finally, that to the mapped vertex. In + // most cases this complicated procedure will be the identity. for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) patch.vertices[vertex] = data.mapping_collection[0].transform_unit_to_real_cell (cell_and_face->first, @@ -119,24 +108,22 @@ build_one_patch (const FaceDescriptor *cell_and_face, if (data.n_datasets > 0) { - data.x_fe_values.reinit (cell_and_face->first, cell_and_face->second); - const FEFaceValues &fe_patch_values - = data.x_fe_values.get_present_fe_values (); + data.reinit_all_fe_values(this->dof_data, cell_and_face->first, + cell_and_face->second); + const FEValuesBase &fe_patch_values + = data.get_present_fe_values (0); const unsigned int n_q_points = fe_patch_values.n_quadrature_points; // store the intermediate points Assert(patch.space_dim==DH::dimension, ExcInternalError()); const std::vector > &q_points=fe_patch_values.get_quadrature_points(); - // resize the patch.data member - // in order to have enough memory - // for the quadrature points as - // well + // resize the patch.data member in order to have enough memory for the + // quadrature points as well patch.data.reinit(data.n_datasets+DH::dimension, patch.data.size(1)); - // set the flag indicating that - // for this cell the points are - // explicitly given + // set the flag indicating that for this cell the points are explicitly + // given patch.points_are_available=true; // copy points to patch.data for (unsigned int i=0; idof_data.size(); ++dataset) { + const FEValuesBase &fe_patch_values + = data.get_present_fe_values (dataset); + const unsigned int n_components + = fe_patch_values.get_fe().n_components(); const DataPostprocessor *postprocessor=this->dof_data[dataset]->postprocessor; if (postprocessor != 0) { - // we have to postprocess the - // data, so determine, which - // fields have to be updated + // we have to postprocess the data, so determine, which fields + // have to be updated const UpdateFlags update_flags=postprocessor->get_needed_update_flags(); - // get normals, if - // needed. this is a - // geometrical information - // and thus does not depend - // on the number of - // components of the data + // get normals, if needed. this is a geometrical information and + // thus does not depend on the number of components of the data // vector if (update_flags & update_normal_vectors) data.patch_normals=fe_patch_values.get_normal_vectors(); - if (data.n_components == 1) + if (n_components == 1) { - // at each point there is - // only one component of - // value, gradient etc. + // at each point there is only one component of value, + // gradient etc. if (update_flags & update_values) this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values); @@ -195,10 +180,9 @@ build_one_patch (const FaceDescriptor *cell_and_face, } else { - // at each point there is - // a vector valued - // function and its + // at each point there is a vector valued function and its // derivative... + data.resize_system_vectors(n_components); if (update_flags & update_values) this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values_system); @@ -228,13 +212,10 @@ build_one_patch (const FaceDescriptor *cell_and_face, = data.postprocessed_values[dataset][q](component); } else - // now we use the given data - // vector without - // modifications. again, we - // treat single component - // functions separately for - // efficiency reasons. - if (data.n_components == 1) + // now we use the given data vector without modifications. again, + // we treat single component functions separately for efficiency + // reasons. + if (n_components == 1) { this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values); @@ -243,36 +224,29 @@ build_one_patch (const FaceDescriptor *cell_and_face, } else { + data.resize_system_vectors(n_components); this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values_system); - for (unsigned int component=0; componentdof_data[dataset]->n_output_variables; } // then do the cell data for (unsigned int dataset=0; datasetcell_data.size(); ++dataset) { - // we need to get at - // the number of the - // cell to which this - // face belongs in - // order to access the - // cell data. this is - // not readily - // available, so choose - // the following rather - // inefficient way: + // we need to get at the number of the cell to which this face + // belongs in order to access the cell data. this is not readily + // available, so choose the following rather inefficient way: Assert (cell_and_face->first->active(), ExcCellNotActiveForCellData()); const unsigned int cell_number - = std::distance (this->dofs->begin_active(), - typename DH::active_cell_iterator(cell_and_face->first)); + = std::distance (this->triangulation->begin_active(), + typename Triangulation::active_cell_iterator(cell_and_face->first)); const double value = this->cell_data[dataset]->get_cell_data_value (cell_number); @@ -297,8 +271,7 @@ template void DataOutFaces::build_patches (const Mapping &mapping, const unsigned int n_subdivisions_) { - // Check consistency of redundant - // template parameter + // Check consistency of redundant template parameter Assert (dim==DH::dimension, ExcDimensionMismatch(dim, DH::dimension)); const unsigned int n_subdivisions = (n_subdivisions_ != 0) @@ -309,33 +282,22 @@ void DataOutFaces::build_patches (const Mapping &mapping, ExcInvalidNumberOfSubdivisions(n_subdivisions)); typedef DataOut_DoFData BaseClass; - Assert (this->dofs != 0, typename BaseClass::ExcNoDoFHandlerSelected()); - - // before we start the loop: - // create a quadrature rule that - // actually has the points on this - // patch - const QTrapez<1> q_trapez; - const QIterated patch_points (q_trapez, n_subdivisions); - - const unsigned int n_components = this->dofs->get_fe().n_components(); + Assert (this->triangulation != 0, + typename BaseClass::ExcNoTriangulationSelected()); unsigned int n_datasets = this->cell_data.size(); for (unsigned int i=0; idof_data.size(); ++i) n_datasets += this->dof_data[i]->n_output_variables; - // first count the cells we want to - // create patches of and make sure - // there is enough memory for that + // first count the cells we want to create patches of and make sure there is + // enough memory for that std::vector all_faces; for (FaceDescriptor face=first_face(); - face.first != this->dofs->end(); + face.first != this->triangulation->end(); face = next_face(face)) all_faces.push_back (face); - // clear the patches array and - // allocate the right number of - // elements + // clear the patches array and allocate the right number of elements this->patches.clear (); this->patches.reserve (all_faces.size()); Assert (this->patches.size() == 0, ExcInternalError()); @@ -354,17 +316,17 @@ void DataOutFaces::build_patches (const Mapping &mapping, update_flags |= this->dof_data[i]->postprocessor->get_needed_update_flags(); update_flags |= update_quadrature_points; - internal::DataOutFaces::ParallelData - thread_data (patch_points, n_components, n_datasets, + internal::DataOutFaces::ParallelData + thread_data (n_datasets, n_subdivisions, n_postprocessor_outputs, mapping, - this->dofs->get_fe(), + this->get_finite_elements(), update_flags); DataOutBase::Patch sample_patch; sample_patch.n_subdivisions = n_subdivisions; sample_patch.data.reinit (n_datasets, - patch_points.size()); + Utilities::fixed_power(n_subdivisions+1)); // now build the patches in parallel WorkStream::run (&all_faces[0], @@ -386,8 +348,8 @@ DataOutFaces::first_face () { // simply find first active cell // with a face on the boundary - typename DH::active_cell_iterator cell = this->dofs->begin_active(); - for (; cell != this->dofs->end(); ++cell) + typename Triangulation::active_cell_iterator cell = this->triangulation->begin_active(); + for (; cell != this->triangulation->end(); ++cell) for (unsigned int f=0; f::faces_per_cell; ++f) if (!surface_only || cell->face(f)->at_boundary()) return FaceDescriptor(cell, f); @@ -407,9 +369,7 @@ DataOutFaces::next_face (const FaceDescriptor &old_face) { FaceDescriptor face = old_face; - // first check whether the present - // cell has more faces on the - // boundary + // first check whether the present cell has more faces on the boundary for (unsigned int f=face.second+1; f::faces_per_cell; ++f) if (!surface_only || face.first->face(f)->at_boundary()) // yup, that is so, so return it @@ -418,23 +378,19 @@ DataOutFaces::next_face (const FaceDescriptor &old_face) return face; }; - // otherwise find the next active - // cell that has a face on the - // boundary + // otherwise find the next active cell that has a face on the boundary - // convert the iterator to an - // active_iterator and advance - // this to the next active cell - typename DH::active_cell_iterator active_cell = face.first; + // convert the iterator to an active_iterator and advance this to the next + // active cell + typename Triangulation::active_cell_iterator active_cell = face.first; // increase face pointer by one ++active_cell; // while there are active cells - while (active_cell != this->dofs->end()) + while (active_cell != this->triangulation->end()) { - // check all the faces of this - // active cell + // check all the faces of this active cell for (unsigned int f=0; f::faces_per_cell; ++f) if (!surface_only || active_cell->face(f)->at_boundary()) { @@ -442,15 +398,12 @@ DataOutFaces::next_face (const FaceDescriptor &old_face) face.second = f; return face; }; - // the present cell had no - // faces on the boundary, so - // check next cell + // the present cell had no faces on the boundary, so check next cell ++active_cell; }; - // we fell off the edge, so return - // with invalid pointer - face.first = this->dofs->end(); + // we fell off the edge, so return with invalid pointer + face.first = this->triangulation->end(); face.second = 0; return face; } diff --git a/deal.II/source/numerics/data_out_rotation.cc b/deal.II/source/numerics/data_out_rotation.cc index a78854ada6..5593d7a792 100644 --- a/deal.II/source/numerics/data_out_rotation.cc +++ b/deal.II/source/numerics/data_out_rotation.cc @@ -49,37 +49,31 @@ namespace internal namespace DataOutRotation { template - template ParallelData:: - ParallelData (const Quadrature &quadrature, - const unsigned int n_components, - const unsigned int n_datasets, + ParallelData (const unsigned int n_datasets, const unsigned int n_subdivisions, const unsigned int n_patches_per_circle, const std::vector &n_postprocessor_outputs, - const FE &finite_elements, + const Mapping &mapping, + const std::vector > > &finite_elements, const UpdateFlags update_flags) : internal::DataOut:: - ParallelDataBase (n_components, - n_datasets, + ParallelDataBase (n_datasets, n_subdivisions, - quadrature.size(), n_postprocessor_outputs, - finite_elements), - n_patches_per_circle (n_patches_per_circle), - q_collection (quadrature), - x_fe_values (this->fe_collection, - q_collection, - update_flags) + mapping, + finite_elements, + update_flags, + false), + n_patches_per_circle (n_patches_per_circle) {} + /** - * In a WorkStream context, use - * this function to append the - * patch computed by the parallel - * stage to the array of patches. + * In a WorkStream context, use this function to append the patch computed + * by the parallel stage to the array of patches. */ template void @@ -106,10 +100,8 @@ build_one_patch (const cell_iterator *cell, { if (dim == 3) { - // would this function make any - // sense after all? who would want - // to output/compute in four space - // dimensions? + // would this function make any sense after all? who would want to + // output/compute in four space dimensions? Assert (false, ExcNotImplemented()); return; } @@ -119,20 +111,13 @@ build_one_patch (const cell_iterator *cell, const unsigned int n_patches_per_circle = data.n_patches_per_circle; - // another abbreviation denoting - // the number of q_points in each - // direction + // another abbreviation denoting the number of q_points in each direction const unsigned int n_points = data.n_subdivisions+1; - // set up an array that holds the - // directions in the plane of - // rotation in which we will put - // points in the whole domain (not - // the rotationally reduced one in - // which the computation took - // place. for simplicity add the - // initial direction at the end - // again + // set up an array that holds the directions in the plane of rotation in + // which we will put points in the whole domain (not the rotationally + // reduced one in which the computation took place. for simplicity add the + // initial direction at the end again std::vector > angle_directions (n_patches_per_circle+1); for (unsigned int i=0; i<=n_patches_per_circle; ++i) { @@ -144,13 +129,9 @@ build_one_patch (const cell_iterator *cell, for (unsigned int angle=0; angle v = (*cell)->vertex(vertex); - // make sure that the - // radial variable does - // attain negative + // make sure that the radial variable does attain negative // values Assert (v(0) >= 0, ExcRadialVariableHasNegativeValues(v(0))); - // now set the vertices - // of the patch + // now set the vertices of the patch patches[angle].vertices[vertex] = v(0) * angle_directions[angle]; patches[angle].vertices[vertex][0] = v(1); @@ -205,13 +183,14 @@ build_one_patch (const cell_iterator *cell, // then fill in data if (data.n_datasets > 0) { - data.x_fe_values.reinit (*cell); - const FEValues &fe_patch_values - = data.x_fe_values.get_present_fe_values (); - + data.reinit_all_fe_values(this->dof_data, *cell); // first fill dof_data for (unsigned int dataset=0; datasetdof_data.size(); ++dataset) { + const FEValuesBase & fe_patch_values + = data.get_present_fe_values(dataset); + const unsigned int n_components + = fe_patch_values.get_fe().n_components(); const DataPostprocessor *postprocessor=this->dof_data[dataset]->postprocessor; if (postprocessor != 0) { @@ -220,7 +199,7 @@ build_one_patch (const cell_iterator *cell, // fields have to be updated const UpdateFlags update_flags=postprocessor->get_needed_update_flags(); - if (data.n_components == 1) + if (n_components == 1) { // at each point there is // only one component of @@ -249,10 +228,10 @@ build_one_patch (const cell_iterator *cell, } else { - // at each point there is - // a vector valued - // function and its - // derivative... + data.resize_system_vectors(n_components); + + // at each point there is a vector valued function and + // its derivative... if (update_flags & update_values) this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values_system); @@ -306,7 +285,7 @@ build_one_patch (const cell_iterator *cell, } } } - else if (data.n_components == 1) + else if (n_components == 1) { this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values); @@ -339,10 +318,11 @@ build_one_patch (const cell_iterator *cell, else // system of components { + data.resize_system_vectors(n_components); this->dof_data[dataset]->get_function_values (fe_patch_values, data.patch_values_system); - for (unsigned int component=0; componentcell_data.size(); ++dataset) { - // we need to get at - // the number of the - // cell to which this - // face belongs in - // order to access the - // cell data. this is - // not readily - // available, so choose - // the following rather - // inefficient way: + // we need to get at the number of the cell to which this face + // belongs in order to access the cell data. this is not readily + // available, so choose the following rather inefficient way: Assert ((*cell)->active(), ExcMessage("Cell must be active for cell data")); const unsigned int cell_number - = std::distance (this->dofs->begin_active(), - typename DH::active_cell_iterator(*cell)); + = std::distance (this->triangulation->begin_active(), + typename Triangulation::active_cell_iterator(*cell)); const double value = this->cell_data[dataset]->get_cell_data_value (cell_number); switch (DH::dimension) @@ -434,7 +407,8 @@ void DataOutRotation::build_patches (const unsigned int n_patches_per_ci // template parameter Assert (dim==DH::dimension, ExcDimensionMismatch(dim, DH::dimension)); typedef DataOut_DoFData BaseClass; - Assert (this->dofs != 0, typename BaseClass::ExcNoDoFHandlerSelected()); + Assert (this->triangulation != 0, + typename BaseClass::ExcNoTriangulationSelected()); const unsigned int n_subdivisions = (nnnn_subdivisions != 0) ? nnnn_subdivisions @@ -442,10 +416,6 @@ void DataOutRotation::build_patches (const unsigned int n_patches_per_ci Assert (n_subdivisions >= 1, ExcInvalidNumberOfSubdivisions(n_subdivisions)); - const QTrapez<1> q_trapez; - const QIterated patch_points (q_trapez, n_subdivisions); - - const unsigned int n_components = this->dofs->get_fe().n_components(); unsigned int n_datasets=this->cell_data.size(); for (unsigned int i=0; idof_data.size(); ++i) n_datasets+= this->dof_data[i]->n_output_variables; @@ -465,7 +435,7 @@ void DataOutRotation::build_patches (const unsigned int n_patches_per_ci // create patches of and make sure // there is enough memory for that std::vector all_cells; - for (cell_iterator cell=first_cell(); cell != this->dofs->end(); + for (cell_iterator cell=first_cell(); cell != this->triangulation->end(); cell = next_cell(cell)) all_cells.push_back (cell); @@ -485,10 +455,11 @@ void DataOutRotation::build_patches (const unsigned int n_patches_per_ci else n_postprocessor_outputs[dataset] = 0; + const MappingQ1 mapping; internal::DataOutRotation::ParallelData - thread_data (patch_points, n_components, n_datasets, + thread_data (n_datasets, n_subdivisions, n_patches_per_circle, - n_postprocessor_outputs, this->dofs->get_fe(), + n_postprocessor_outputs, mapping, this->get_finite_elements(), update_flags); std::vector > new_patches (n_patches_per_circle); @@ -496,8 +467,7 @@ void DataOutRotation::build_patches (const unsigned int n_patches_per_ci { new_patches[i].n_subdivisions = n_subdivisions; new_patches[i].data.reinit (n_datasets, - patch_points.size() - * (n_subdivisions+1)); + Utilities::fixed_power(n_subdivisions+1)); } // now build the patches in parallel @@ -518,7 +488,7 @@ template typename DataOutRotation::cell_iterator DataOutRotation::first_cell () { - return this->dofs->begin_active (); + return this->triangulation->begin_active (); } @@ -529,7 +499,7 @@ DataOutRotation::next_cell (const cell_iterator &cell) // convert the iterator to an // active_iterator and advance // this to the next active cell - typename DH::active_cell_iterator active_cell = cell; + typename Triangulation::active_cell_iterator active_cell = cell; ++active_cell; return active_cell; } diff --git a/deal.II/source/numerics/vector_tools.inst.in b/deal.II/source/numerics/vector_tools.inst.in index 7d0327b866..f7bbff340e 100644 --- a/deal.II/source/numerics/vector_tools.inst.in +++ b/deal.II/source/numerics/vector_tools.inst.in @@ -577,6 +577,22 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS std::map&, std::vector); + template + void project_boundary_values + (const Mapping &, + const DoFHandler &, + const FunctionMap::type &, + const Quadrature&, + ConstraintMatrix&, std::vector); + + template + void project_boundary_values + (const DoFHandler &, + const FunctionMap::type &, + const Quadrature&, + ConstraintMatrix&, + std::vector); + #if deal_II_dimension != 1