SET(CONFIG_LIBRARIES_${_build}
\${DEAL_II_PATH}/\${DEAL_II_LIBRARY_RELDIR}/${CONFIG_LIBRARY_${_build}}
- ${DEAL_II_EXTERNAL_LIBRARIES}
${DEAL_II_EXTERNAL_LIBRARIES_${_build}}
+ ${DEAL_II_EXTERNAL_LIBRARIES}
)
LIST(APPEND CONFIG_LIBRARIES
${_keyword}
#
SET(_libs)
FOREACH(_lib
- ${DEAL_II_EXTERNAL_LIBRARIES}
${DEAL_II_EXTERNAL_LIBRARIES_${build}}
+ ${DEAL_II_EXTERNAL_LIBRARIES}
)
IF(_lib MATCHES "^\\s*/")
LIST(APPEND _libs "${_lib}")
SET(_paths)
FOREACH(_lib
$(D)/${DEAL_II_LIBRARY_RELDIR}/${CONFIG_LIBRARY_${build}}
- ${DEAL_II_EXTERNAL_LIBRARIES}
${DEAL_II_EXTERNAL_LIBRARIES_${build}}
+ ${DEAL_II_EXTERNAL_LIBRARIES}
)
#
MACRO(FEATURE_LAPACK_CONFIGURE_EXTERNAL)
ADD_FLAGS(DEAL_II_LINKER_FLAGS "${LAPACK_LINKER_FLAGS}")
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${LAPACK_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${LAPACK_LIBRARIES})
CHECK_FOR_LAPACK_FUNCTIONS()
ENDMACRO()
ADD_FLAGS(CMAKE_CXX_FLAGS "${MPI_CXX_COMPILE_FLAGS}")
ADD_FLAGS(DEAL_II_LINKER_FLAGS "${MPI_CXX_LINK_FLAGS}")
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${MPI_CXX_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${MPI_CXX_LIBRARIES})
INCLUDE_DIRECTORIES(${MPI_CXX_INCLUDE_PATH})
# The user has to know the location of the mpi headers as well:
MACRO(FEATURE_THREADS_CONFIGURE_EXTERNAL)
INCLUDE_DIRECTORIES(${TBB_INCLUDE_DIR})
- SPLIT_DEBUG_RELEASE(_tbb_debug _tbb_release ${TBB_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${TBB_LIBRARIES})
IF(CMAKE_BUILD_TYPE MATCHES "Debug")
IF(TBB_WITH_DEBUG_LIB)
)
ENDIF()
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES_DEBUG ${_tbb_debug})
ENDIF()
- IF(CMAKE_BUILD_TYPE MATCHES "Release")
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES_RELEASE ${_tbb_release})
- ENDIF()
SETUP_THREADING()
ENDMACRO()
FIND_LIBRARY(dl_LIBRARY NAMES dl)
MARK_AS_ADVANCED(dl_LIBRARY)
IF(NOT dl_LIBRARY MATCHES "-NOTFOUND")
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${dl_LIBRARY})
+ DEAL_II_APPEND_LIBRARIES(${dl_LIBRARY})
ENDIF()
INCLUDE_DIRECTORIES(${TBB_FOLDER}/include)
SET(METIS_DIR "" CACHE PATH
"An optional hint to a metis directory"
)
+ MARK_AS_ADVANCED(CLEAR METIS_DIR)
ENDIF()
ENDIF()
ENDMACRO()
SET(PETSC_ARCH "" CACHE STRING
"An optional hint to a PETSc arch"
)
+ MARK_AS_ADVANCED(CLEAR PETSC_DIR PETSC_ARCH)
ENDIF()
ENDIF()
ENDMACRO()
# The user has to know the location of the petsc headers as well:
LIST(APPEND DEAL_II_USER_INCLUDE_DIRS ${PETSC_INCLUDE_DIRS})
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${PETSC_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${PETSC_LIBRARIES})
#
# Disable a bunch of warnings when compiling with petsc:
ENDIF()
ENDIF(TRILINOS_FOUND)
+
+ IF(NOT ${var})
+ UNSET(TRILINOS_CONFIG CACHE)
+ SET(TRILINOS_DIR "" CACHE STRING
+ "An optional hint to a Trilinos installation"
+ )
+ MARK_AS_ADVANCED(CLEAR TRILINOS_DIR)
+ ENDIF()
+
ENDMACRO()
# The user has to know the location of the trilinos headers as well:
LIST(APPEND DEAL_II_USER_INCLUDE_DIRS ${TRILINOS_INCLUDE_DIRS})
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${TRILINOS_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${TRILINOS_LIBRARIES})
SET(DEAL_II_EXPAND_TRILINOS_VECTOR "TrilinosWrappers::Vector")
SET(DEAL_II_EXPAND_TRILINOS_BLOCKVECTOR "TrilinosWrappers::BlockVector")
IF(NOT FEATURE_THREADS_PROCESSED)
MESSAGE(FATAL_ERROR "\n"
"Internal build system error:\n"
- "configure_boost.cmake included before configure_tbb.cmake\n\n"
+ "configure_boost.cmake included before configure_1_threads.cmake\n\n"
)
ENDIF()
MACRO(FEATURE_BOOST_FIND_EXTERNAL var)
- SET_IF_EMPTY(BOOST_DIR "$ENV{BOOST_DIR}")
+ IF(NOT DEFINED BOOST_DIR)
+ SET(BOOST_DIR "$ENV{BOOST_DIR}")
+ ELSE()
+ SET_IF_EMPTY(BOOST_DIR "$ENV{BOOST_DIR}")
+ ENDIF()
IF(NOT "${BOOST_DIR}" STREQUAL "")
SET(BOOST_ROOT "${BOOST_DIR}")
ENDIF()
#
LIST(REMOVE_ITEM Boost_LIBRARIES "pthread")
- #
- # Transform Boost_LIBRARIES into a list of debug and release libraries
- # without keywords:
- #
- SPLIT_DEBUG_RELEASE(_boost_debug _boost_release ${Boost_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${Boost_LIBRARIES})
- IF (CMAKE_BUILD_TYPE MATCHES "Debug")
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES_DEBUG ${_boost_debug})
- ENDIF()
-
- IF (CMAKE_BUILD_TYPE MATCHES "Release")
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES_RELEASE ${_boost_release})
- ENDIF()
ENDMACRO()
" HDF5_WITH_MPI = ${HDF5_WITH_MPI}\n"
)
ENDIF()
+
+ INCLUDE_DIRECTORIES(${HDF5_INCLUDE_DIRS})
+ LIST(APPEND DEAL_II_USER_INCLUDE_DIRS ${HDF5_INCLUDE_DIRS})
+ DEAL_II_APPEND_LIBRARIES(${HDF5_LIBRARIES})
+
+
ENDIF()
ENDMACRO()
# The user has to know the location of the MUMPS headers as well:
LIST(APPEND DEAL_II_USER_INCLUDE_DIRS ${MUMPS_INCLUDE_DIRS})
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${MUMPS_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${MUMPS_LIBRARIES})
ENDMACRO()
CONFIGURE_FEATURE(MUMPS)
"p4est has to be configured with MPI enabled.\n"
)
- UNSET(P4EST_LIBRARY CACHE)
+ UNSET(P4EST_LIBRARY_OPTIMIZED CACHE)
+ UNSET(P4EST_LIBRARY_DEBUG CACHE)
UNSET(P4EST_INCLUDE_DIR CACHE)
- UNSET(SC_LIBRARY CACHE)
+ UNSET(SC_LIBRARY_OPTIMIZED CACHE)
+ UNSET(SC_LIBRARY_DEBUG CACHE)
UNSET(SC_INCLUDE_DIR CACHE)
SET(P4EST_DIR "" CACHE PATH
"An optional hint to a p4est installation/directory"
)
+ MARK_AS_ADVANCED(CLEAR P4EST_DIR)
ELSE()
SET(${var} TRUE)
ENDIF()
# The user has to know the location of the P4EST headers as well:
LIST(APPEND DEAL_II_USER_INCLUDE_DIRS ${P4EST_INCLUDE_DIRS})
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${P4EST_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${P4EST_LIBRARIES})
ENDMACRO()
CONFIGURE_FEATURE(P4EST)
SET(SLEPC_DIR "" CACHE PATH
"An optional hint to a SLEPc directory"
)
+ MARK_AS_ADVANCED(CLEAR SLEPC_DIR)
SET(${var} FALSE)
ENDIF()
# The user has to know the location of the SLEPC headers as well:
LIST(APPEND DEAL_II_USER_INCLUDE_DIRS ${SLEPC_INCLUDE_DIRS})
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${SLEPC_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${SLEPC_LIBRARIES})
ENDMACRO()
INCLUDE_DIRECTORIES(${${_feature}_INCLUDE_DIRS})
ENDIF()
IF(DEFINED ${_feature}_LIBRARIES)
- LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${${_feature}_LIBRARIES})
+ DEAL_II_APPEND_LIBRARIES(${${_feature}_LIBRARIES})
ENDIF()
IF(DEFINED ${_feature}_LINKER_FLAGS)
ADD_FLAGS(DEAL_II_LINKER_FLAGS "${${_feature}_LINKER_FLAGS}")
##
## ---------------------------------------------------------------------
-
#
-# A small macro to split a list of libraries with debug, optimized and
-# general keywords into two lists consisting of all libraries necessary for
-# the debug and release target only. If no keyword is given "optimized" is
-# assumed.
+# A small macro to add libraries to
+# DEAL_II_EXTERNAL_LIBRARIES
+# DEAL_II_EXTERNAL_LIBRARIES_DEBUG
+# DEAL_II_EXTERNAL_LIBRARIES_RELEASE
+# depending on the "optmized", "debug" or "general" keyword
#
# Usage:
-# SPLIT_DEBUG_RELEASE(list_debug list_release <...list of libraries...>)
-#
+# DEAL_II_APPEND_LIBRARIES(<list of libraries>)
#
-MACRO(SPLIT_DEBUG_RELEASE _list_debug _list_release)
+MACRO(DEAL_II_APPEND_LIBRARIES)
- SET(_toggle "optimized")
+ SET(_toggle "general")
FOREACH(_tmp ${ARGN})
- IF("${_tmp}" STREQUAL "debug" OR
- "${_tmp}" STREQUAL "optimized" OR
- "${_tmp}" STREQUAL "general")
+ IF( "${_tmp}" STREQUAL "debug" OR
+ "${_tmp}" STREQUAL "optimized" OR
+ "${_tmp}" STREQUAL "general" )
SET(_toggle "${_tmp}")
ELSE()
IF("${_toggle}" STREQUAL "general")
- LIST(APPEND ${_list_debug} "${_tmp}")
- LIST(APPEND ${_list_release} "${_tmp}")
+ LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES ${_tmp})
ELSEIF("${_toggle}" STREQUAL "debug")
- LIST(APPEND ${_list_debug} "${_tmp}")
+ LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES_DEBUG ${_tmp})
ELSEIF("${_toggle}" STREQUAL "optimized")
- LIST(APPEND ${_list_release} "${_tmp}")
+ LIST(APPEND DEAL_II_EXTERNAL_LIBRARIES_RELEASE ${_tmp})
ENDIF()
ENDIF()
ENDFOREACH()
- IF("${${_list_debug}}" STREQUAL "")
- SET(${_list_debug} ${${_list_release}})
- ELSEIF("${${_list_release}}" STREQUAL "")
- SET(${_list_release} ${${_list_debug}})
- ENDIF()
-
ENDMACRO()
# METIS_VERSION
# METIS_VERSION_MAJOR
# METIS_VERSION_MINOR
+# METIS_VERSION_SUBMINOR
#
INCLUDE(FindPackageHandleStandardArgs)
SET_IF_EMPTY(P4EST_DIR "$ENV{P4EST_DIR}")
SET_IF_EMPTY(SC_DIR "$ENV{SC_DIR}")
-#
-# We used to recommend installing p4est with a custom script that
-# compiled p4est twice, once in debug and once in optimized mode.
-# the installation would then have happened into directories
-# $P4EST_DIR/DEBUG and $P4EST_DIR/FAST. If we can find these
-# two directories, then use the FAST directory rather than trying
-# to figure out how we can build deal.II against the two libraries
-# depending on whether we are in debug or optimized mode.
-#
-IF(P4EST_DIR
- AND EXISTS ${P4EST_DIR}/DEBUG
- AND EXISTS ${P4EST_DIR}/FAST)
- MESSAGE(STATUS "Found old-style p4est directory layout")
- SET (P4EST_DIR ${P4EST_DIR}/FAST)
-ENDIF()
-
-
#
# Search for the sc library, usually bundled with p4est. If no SC_DIR was
# given, take what we chose for p4est.
FIND_PATH(P4EST_INCLUDE_DIR p4est_config.h
HINTS
+ ${P4EST_DIR}/FAST
+ ${P4EST_DIR}/DEBUG
${P4EST_DIR}
PATH_SUFFIXES
p4est include/p4est include src
FIND_PATH(SC_INCLUDE_DIR sc.h
HINTS
+ ${SC_DIR}/FAST
+ ${SC_DIR}/DEBUG
${SC_DIR}
+ ${P4EST_DIR}/FAST
+ ${P4EST_DIR}/DEBUG
${P4EST_DIR}
PATH_SUFFIXES
sc include/p4est include src sc/src
)
-FIND_LIBRARY(P4EST_LIBRARY
+FIND_LIBRARY(P4EST_LIBRARY_OPTIMIZED
NAMES p4est
HINTS
+ ${P4EST_DIR}/FAST
+ ${P4EST_DIR}/DEBUG
${P4EST_DIR}
PATH_SUFFIXES
lib${LIB_SUFFIX} lib64 lib src
)
-FIND_LIBRARY(SC_LIBRARY
+FIND_LIBRARY(P4EST_LIBRARY_DEBUG
+ NAMES p4est
+ HINTS
+ ${P4EST_DIR}/DEBUG
+ PATH_SUFFIXES
+ lib${LIB_SUFFIX} lib64 lib src
+ )
+
+FIND_LIBRARY(SC_LIBRARY_OPTIMIZED
NAMES sc
HINTS
+ ${SC_DIR}/FAST
+ ${SC_DIR}/DEBUG
${SC_DIR}
+ ${P4EST_DIR}/FAST
+ ${P4EST_DIR}/DEBUG
${P4EST_DIR}
PATH_SUFFIXES
lib${LIB_SUFFIX} lib64 lib src sc/src
)
-SET(_output ${P4EST_LIBRARY} ${SC_LIBRARY})
+FIND_LIBRARY(SC_LIBRARY_DEBUG
+ NAMES sc
+ HINTS
+ ${SC_DIR}/DEBUG
+ ${P4EST_DIR}/DEBUG
+ PATH_SUFFIXES
+ lib${LIB_SUFFIX} lib64 lib src sc/src
+ )
+
+SET(_output ${P4EST_LIBRARY_OPTMIZED} ${SC_LIBRARY_OPTIMIZED})
FIND_PACKAGE_HANDLE_STANDARD_ARGS(P4EST DEFAULT_MSG
_output # Cosmetic: Gives nice output
- P4EST_LIBRARY
- SC_LIBRARY
+ P4EST_LIBRARY_OPTIMIZED
+ SC_LIBRARY_OPTIMIZED
P4EST_INCLUDE_DIR
SC_INCLUDE_DIR
)
MARK_AS_ADVANCED(
- P4EST_LIBRARY
+ P4EST_LIBRARY_OPTIMIZED
+ P4EST_LIBRARY_DEBUG
P4EST_INCLUDE_DIR
- SC_LIBRARY
+ SC_LIBRARY_OPTIMIZED
+ SC_LIBRARY_DEBUG
SC_INCLUDE_DIR
)
+
IF(P4EST_FOUND)
- SET(P4EST_LIBRARIES
- ${P4EST_LIBRARY}
- ${SC_LIBRARY}
+
+ IF( ( "${P4EST_LIBRARY_OPTIMIZED}" STREQUAL "${P4EST_LIBRARY_DEBUG}"
+ AND
+ "${SC_LIBRARY_OPTIMIZED}" STREQUAL "${SC_LIBRARY_DEBUG}" )
+ OR P4EST_LIBRARY_DEBUG MATCHES "-NOTFOUND"
+ OR SC_LIBRARY_DEBUG MATCHES "-NOTFOUND" )
+ SET(P4EST_LIBRARIES
+ ${P4EST_LIBRARY_OPTIMIZED}
+ ${SC_LIBRARY_OPTIMIZED}
+ )
+ ELSE()
+ SET(P4EST_LIBRARIES
+ optimized
+ ${P4EST_LIBRARY_OPTIMIZED}
+ ${SC_LIBRARY_OPTIMIZED}
+ debug
+ ${P4EST_LIBRARY_DEBUG}
+ ${SC_LIBRARY_DEBUG}
+ general
+ )
+ ENDIF()
+
+ LIST(APPEND P4EST_LIBRARIES
${LAPACK_LIBRARIES} # for good measure
${MPI_C_LIBRARIES} # for good measure
)
IF("${P4EST_MPI_STRING}" STREQUAL "")
SET(P4EST_WITH_MPI FALSE)
ELSE()
+
SET(P4EST_WITH_MPI TRUE)
ENDIF()
NO_CMAKE_FIND_ROOT_PATH
)
+ MARK_AS_ADVANCED(TRILINOS_LIBRARY_${_library})
+
IF(TRILINOS_LIBRARY_${_library} MATCHES "-NOTFOUND")
SET(TRILINOS_CONFIG_FOUND FALSE)
ELSE()
# SET(METIS_FOUND TRUE CACHE BOOL "")
# SET(METIS_LIBRARIES "library;and;semicolon;separated;list;of;link;interface" CACHE STRING "")
# SET(METIS_INCLUDE_DIRS "semicolon;separated;list;of;include;dirs" CACHE STRING "")
+# SET(METIS_VERSION "x.y.z" CACHE STRING "")
+# SET(METIS_VERSION_MAJOR "x" CACHE STRING "")
+# SET(METIS_VERSION_MINOR "y" CACHE STRING "")
+# SET(METIS_VERSION_SUBMINOR "z" CACHE STRING "")
#
# SET(P4EST_LIBRARIES "library;and;semicolon;separated;list;of;link;interface" CACHE STRING "")
# SET(P4EST_INCLUDE_DIRS "semicolon;separated;list;of;include;dirs" CACHE STRING "")
# SET(P4EST_WITH_MPI TRUE CACHE BOOL "")
+# SET(P4EST_VERSION "x.y.z.p" CACHE STRING "")
+# SET(P4EST_VERSION_MAJOR "x" CACHE STRING "")
+# SET(P4EST_VERSION_MINOR "y" CACHE STRING "")
+# SET(P4EST_VERSION_SUBMINOR "z" CACHE STRING "")
+# SET(P4EST_VERSION_PATCH "p" CACHE STRING "")
#
# SET(PETSC_VERSION_MAJOR "x" CACHE STRING "")
# SET(PETSC_VERSION_MINOR "y" CACHE STRING "")
# SET(PETSC_VERSION_SUBMINOR "z" CACHE STRING "")
+# SET(PETSC_VERSION_PATCH "" CACHE STRING "")
# SET(PETSC_WITH_MPI_UNI FALSE CACHE BOOL "")
#
# SET(SLEPC_VERSION_MAJOR "x" CACHE STRING "")
# SET(SLEPC_VERSION_MINOR "y" CACHE STRING "")
# SET(SLEPC_VERSION_SUBMINOR "z" CACHE STRING "")
+# SET(SLEPC_VERSION_PATCH "" CACHE STRING "")
# SET(SLEPC_WITH_MPI_UNI FALSE CACHE BOOL "")
#
<link href="screen.css" rel="StyleSheet" type="text/css">
<title>The deal.II Online Documentation</title>
<meta name="author" content="the deal.II authors <authors@dealii.org>">
- <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 by the deal.II authors">
+ <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 by the deal.II authors">
<meta name="date" content="2006/02/07 22:49:01">
<meta name="keywords" content="deal.II">
<meta name="svn_id" content="$Id$">
</head>
<body>
+
+
+
<h2>Online documentation</h2>
+ <table class="tutorial" width="40%">
+ <tr><th colspan="2"><b><small>Table of contents</small></b></th></tr>
+ <tr><td valign="top">
+ <ul>
+ <li> <a href="#readme.html">ReadMe</a></li>
+ <li> <a href="#tutorials">Tutorials</a></li>
+ <li> <a href="#API">Programming interface</a></li>
+ <li> <a href="#dev">Development information</a></li>
+ <li> <a href="#reports">Reports</a></li>
+ <li> <a href="#publications">Publications</a></li>
+ <li> <a href="#license">Copyright and licence</a></li>
+ </ul>
+ </td>
+ </tr>
+ </table>
+
+
<p>
<acronym>deal.II</acronym> comes with quite extensive online
documentation, which falls into several categories. They are
</p>
- <h3><a href="readme.html">README</a></h3>
+ <h3><a href="readme.html">ReadMe</a></h3>
<p>
First, there is the <a href="readme.html" target="body">README file</a> of
installation, and copyright.
</p>
- <h3>Tutorials</h3>
+ <h3><a href="tutorials">Tutorials</a></h3>
<p>
The <a href="doxygen/tutorial/index.html"
</p>
- <h3>Programming interface</h3>
+ <h3><a href="API">Programming interface</a></h3>
<p>
The <a href="doxygen/deal.II/index.html" target="_top">programming
</p>
- <h3>Development information</h3>
+ <h3><a name="dev">Development information</a></h3>
<p>
If you plan to <a href="development/index.html"
</p>
- <h3>Reports</h3>
+ <h3><a name="reports">Reports</a></h3>
<p>
There are a number of papers that describe the overall design or
</ul>
- <h3>Publications</h3>
+ <h3><a name="publications">Publications</a></h3>
<p>
A <a href="publications/index.html" target="body">list of
</p>
- <h3>Copyright and License</h3>
+ <h3><a name="license">Copyright and License</a></h3>
<p> <acronym>deal.II</acronym> is copyright of the
<a href="authors.html" target="body">deal.II authors</a>.
<br>
(Wolfgang Bangerth, 2013/08/09)
</li>
+
+ <li>
+ Changed: The typedefs DataOut::cell_iterator and
+ DataOut::active_cell_iterator were previously defined as
+ DoFHandler::(active)_cell_iterator, while they are now
+ Triangulation::(active)_cell_iterator. This is necessary to support DataOut
+ on multiple DoFHandler objects. This affects possible overloading of
+ DataOut::next_cell(cell_iterator). Use the typedef
+ DataOut::(active)_cell_iterator as argument type instead.
+ <br>
+ (Martin Kronbichler, 2013/07/24)
+ </li>
</ol>
<h3>Specific improvements</h3>
<ol>
+ <li>
+ Fixed: The ParameterHandler class can now deal with including one parameter
+ file from another.
+ <br>
+ (Wolfgang Bangerth, 2013/08/25)
+ </li>
+
+ <li>
+ New: The method VectorTools::compute_normal_flux_constraints can be used to
+ force a vector finite element function to be normal to the boundary.
+ <br>
+ (Martin Kronbichler, 2013/08/23)
+ </li>
+
+ <li>
+ Improved: MappingQ now uses the points of the Gauss-Lobatto quadrature
+ formula as support points instead of equispaced ones. This allows its use
+ for high polynomial orders and also gives better interpolation of circular
+ boundaries. Beware that mappings of order three and higher will behave
+ slightly differently now (usually better).
+ <br>
+ (Martin Kronbichler, 2013/08/23)
+ </li>
+
+ <li>
+ Improved: Several .cc files in the deal.II directory have been split in
+ order to better utilize multiple processors when compiling in parallel and
+ reduce memory requirements of the compilation stage.
+ <br>
+ (Martin Kronbichler, 2013/08/22)
+ </li>
+
+ <li>
+ Fixed: The ParameterHandler::declare_entry() did not check that the
+ default value of a parameter indeed satisfies the pattern given for this
+ parameter (despite a statement in the documentation that this checking
+ would happen). This is now fixed.
+ <br>
+ (Wolfgang Bangerth, 2013/08/21)
+ </li>
+
+ <li>
+ New: Patterns::List and Patterns::Map now accept a string
+ different than the default comma that denotes the separator
+ between entries of the list or map.
+ <br>
+ (Wolfgang Bangerth, 2013/08/21)
+ </li>
+
+ <li>
+ Fixed: Some operations in the MappingQ class are now done in higher
+ precision arithmetic to mitigate the ill-conditioning that appears
+ when using mappings of high order (say, order 6 or 8 or 10).
+ <br>
+ (Juan Carlos Araujo Cabarcas, 2013/08/20)
+ </li>
+
+ <li>
+ Fixed: The SLEPcWrappers classes could not be compiled for 64-bit
+ indices. This is now fixed.
+ <br>
+ (Denis Davydov, Wolfgang Bangerth, 2013/08/20)
+ </li>
+
+ <li>
+ Fixed: SolutionTransfer used to crash whenever one transfered in the hp
+ context between cells that use FE_Nothing and FE_Q. This is now fixed.
+ <br>
+ (Krzyszof Bzowski, Wolfgang Bangerth, 2013/08/18)
+ </li>
+
<li>
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
@code
set style data lines
set size 0.721, 1
-set nokey
+unset key
plot [-1:1][-1:1] "ball0_mapping_q1.dat"
@endcode
or using one of the other filenames. The second line makes sure that
Computation of Pi by the area:
==============================
Degree = 1
-cells eval.pi error
-5 1.9999999999999998 1.1416e+00 -
-20 2.8284271247461898 3.1317e-01 1.87
-80 3.0614674589207178 8.0125e-02 1.97
-320 3.1214451522580520 2.0148e-02 1.99
-1280 3.1365484905459389 5.0442e-03 2.00
-5120 3.1403311569547521 1.2615e-03 2.00
+cells eval.pi error
+ 5 1.9999999999999993 1.1416e+00 -
+ 20 2.8284271247461894 3.1317e-01 1.87
+ 80 3.0614674589207178 8.0125e-02 1.97
+ 320 3.1214451522580520 2.0148e-02 1.99
+ 1280 3.1365484905459393 5.0442e-03 2.00
+ 5120 3.1403311569547534 1.2615e-03 2.00
Degree = 2
-cells eval.pi error
-5 3.1045694996615869 3.7023e-02 -
-20 3.1391475703122276 2.4451e-03 3.92
-80 3.1414377167038303 1.5494e-04 3.98
-320 3.1415829366419019 9.7169e-06 4.00
-1280 3.1415920457576907 6.0783e-07 4.00
-5120 3.1415926155921126 3.7998e-08 4.00
+cells eval.pi error
+ 5 3.1045694996615865 3.7023e-02 -
+ 20 3.1391475703122271 2.4451e-03 3.92
+ 80 3.1414377167038303 1.5494e-04 3.98
+ 320 3.1415829366419015 9.7169e-06 4.00
+ 1280 3.1415920457576911 6.0783e-07 4.00
+ 5120 3.1415926155921139 3.7998e-08 4.00
Degree = 3
-cells eval.pi error
-5 3.1465390309173475 4.9464e-03 -
-20 3.1419461263297386 3.5347e-04 3.81
-80 3.1416154689089382 2.2815e-05 3.95
-320 3.1415940909713274 1.4374e-06 3.99
-1280 3.1415927436051230 9.0015e-08 4.00
-5120 3.1415926592185492 5.6288e-09 4.00
+cells eval.pi error
+ 5 3.1410033851499310 5.8927e-04 -
+ 20 3.1415830393583861 9.6142e-06 5.94
+ 80 3.1415925017363837 1.5185e-07 5.98
+ 320 3.1415926512106722 2.3791e-09 6.00
+ 1280 3.1415926535525962 3.7197e-11 6.00
+ 5120 3.1415926535892140 5.7923e-13 6.00
Degree = 4
-cells eval.pi error
-5 3.1418185737113964 2.2592e-04 -
-20 3.1415963919525050 3.7384e-06 5.92
-80 3.1415927128397780 5.9250e-08 5.98
-320 3.1415926545188264 9.2903e-10 5.99
-1280 3.1415926536042722 1.4479e-11 6.00
-5120 3.1415926535899668 1.7343e-13 6.38
-
+cells eval.pi error
+ 5 3.1415871927401127 5.4608e-06 -
+ 20 3.1415926314742437 2.2116e-08 7.95
+ 80 3.1415926535026228 8.7170e-11 7.99
+ 320 3.1415926535894529 3.4036e-13 8.00
+ 1280 3.1415926535897927 2.9187e-16 10.19
+ 5120 3.1415926535897944 1.3509e-15 -2.21
Computation of Pi by the perimeter:
===================================
Degree = 1
-cells eval.pi error
-5 2.8284271247461903 3.1317e-01 -
-20 3.0614674589207183 8.0125e-02 1.97
-80 3.1214451522580524 2.0148e-02 1.99
-320 3.1365484905459393 5.0442e-03 2.00
-1280 3.1403311569547525 1.2615e-03 2.00
-5120 3.1412772509327729 3.1540e-04 2.00
+cells eval.pi error
+ 5 2.8284271247461898 3.1317e-01 -
+ 20 3.0614674589207178 8.0125e-02 1.97
+ 80 3.1214451522580520 2.0148e-02 1.99
+ 320 3.1365484905459393 5.0442e-03 2.00
+ 1280 3.1403311569547525 1.2615e-03 2.00
+ 5120 3.1412772509327729 3.1540e-04 2.00
Degree = 2
-cells eval.pi error
-5 3.1248930668550599 1.6700e-02 -
-20 3.1404050605605454 1.1876e-03 3.81
-80 3.1415157631807014 7.6890e-05 3.95
-320 3.1415878042798613 4.8493e-06 3.99
-1280 3.1415923498174538 3.0377e-07 4.00
-5120 3.1415926345932004 1.8997e-08 4.00
+cells eval.pi error
+ 5 3.1248930668550594 1.6700e-02 -
+ 20 3.1404050605605449 1.1876e-03 3.81
+ 80 3.1415157631807014 7.6890e-05 3.95
+ 320 3.1415878042798617 4.8493e-06 3.99
+ 1280 3.1415923498174534 3.0377e-07 4.00
+ 5120 3.1415926345932004 1.8997e-08 4.00
Degree = 3
-cells eval.pi error
-5 3.1442603311164286 2.6677e-03 -
-20 3.1417729561193588 1.8030e-04 3.89
-80 3.1416041192612365 1.1466e-05 3.98
-320 3.1415933731961760 7.1961e-07 3.99
-1280 3.1415926986118001 4.5022e-08 4.00
-5120 3.1415926564043946 2.8146e-09 4.00
+cells eval.pi error
+ 5 3.1414940401456057 9.8613e-05 -
+ 20 3.1415913432549156 1.3103e-06 6.23
+ 80 3.1415926341726914 1.9417e-08 6.08
+ 320 3.1415926532906893 2.9910e-10 6.02
+ 1280 3.1415926535851360 4.6571e-12 6.01
+ 5120 3.1415926535897203 7.2845e-14 6.00
Degree = 4
-cells eval.pi error
-5 3.1417078926581086 1.1524e-04 -
-20 3.1415945317216001 1.8781e-06 5.94
-80 3.1415926832497720 2.9660e-08 5.98
-320 3.1415926540544636 4.6467e-10 6.00
-1280 3.1415926535970535 7.2602e-12 6.00
-5120 3.1415926535899010 1.0805e-13 6.07
+cells eval.pi error
+ 5 3.1415921029432576 5.5065e-07 -
+ 20 3.1415926513737600 2.2160e-09 7.96
+ 80 3.1415926535810712 8.7218e-12 7.99
+ 320 3.1415926535897594 3.3668e-14 8.02
+ 1280 3.1415926535897922 1.0617e-15 4.99
+ 5120 3.1415926535897931 1.0061e-16 3.40
@endcode
-One of the immediate observations from the output is that in all cases
-the values converge quickly to the true value of
-$\pi=3.141592653589793238462643$. Note that for the $Q_4$ mapping, the last
-number is correct to 13 digits in both computations, which is already
-quite a lot. However, also note that for the $Q_1$ mapping, even on the
-finest grid the accuracy is significantly worse than on the coarse
-grid for a $Q_4$ mapping!
+One of the immediate observations from the output is that in all cases the
+values converge quickly to the true value of
+$\pi=3.141592653589793238462643$. Note that for the $Q_4$ mapping, we are
+already in the regime of roundoff errors and the convergence rate levels off,
+which is already quite a lot. However, also note that for the $Q_1$ mapping,
+even on the finest grid the accuracy is significantly worse than on the coarse
+grid for a $Q_3$ mapping!
-The last column of the output shows the convergence order, in powers
-of the mesh width $h$. In the introduction, we had stated that
-the convergence order for a $Q_p$ mapping should be
-$h^{p+1}$. However, in the example shown, the $Q_2$ and $Q_4$
-mappings show a convergence order of $h^{p+2}$! This at
-first surprising fact is readily explained by the particular boundary
-we have chosen in this example. In fact, the circle is described by the function
-$\sqrt{1-x^2}$, which has the series expansion
-$1-x^2/2-x^4/8-x^6/16+\ldots$
-around $x=0$. Thus, for the quadratic mapping where the
-truncation error of the quadratic approximation should be cubic, there
-is no such term but only a quartic one, which raises the convergence
-order to 4, instead of 3. The same happens for the $Q_4$ mapping.
+The last column of the output shows the convergence order, in powers of the
+mesh width $h$. In the introduction, we had stated that the convergence order
+for a $Q_p$ mapping should be $h^{p+1}$. However, in the example shown, the
+order is rather $h^{2p}$! This at first surprising fact is explained by the
+properties of the $Q_p$ mapping. At order <i>p</i>, it uses support points
+that are based on the <i>p</i>+1 point Gauss-Lobatto quadrature rule that
+selects the support points in such a way that the quadrature rule converges at
+order 2<i>p</i>. Even though these points are here only used for interpolation
+of a <i>p</i>th order polynomial, we get a superconvergence effect when
+numerically evaluating the integral that actually gives this high order of
+convergence.
// Finally, we have by now only integrated the gradients of the shape
// functions, not taking their mean value. We fix this by dividing by
// the measure of the volume over which we have integrated:
- rhs.scale (1./total_volume);
+ rhs /= total_volume;
}
}
// As mentioned above this function reads in the
-// obstacle datas and stores them in the std::vector
+// obstacle data and stores them in the std::vector
// obstacle_data. It will be used only in run ().
template<int dim>
void Input<dim>::read_obstacle(const char* name) {
// This class provides an interface
// for a constitutive law. In this
-// example we are using an elasto
-// plastic material behavior with linear,
+// example we are using an elastoplastic
+// material behavior with linear,
// isotropic hardening.
-// For gamma = 0 we obtain perfect elasto
-// plasticity behavior.
+// For gamma = 0 we obtain perfect elastoplastic
+// behavior.
template<int dim>
class ConstitutiveLaw {
public:
// @sect3{ConstitutiveLaw::ConstitutiveLaw}
-// Calculates the strain for the shape functions.
+// Calculates the strain $\varepsilon(\varphi)=\dfrac{1}{2}\left(\nabla\varphi + \nabla\varphi^T$
+// for the shape functions $\varphi$.
template<int dim>
inline SymmetricTensor<2, dim> ConstitutiveLaw<dim>::get_strain(
const FEValues<dim> &fe_values, const unsigned int shape_func,
// 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.
+// points. We need this function to calculate the nonlinear
+// residual in
+// PlasticityContactProblem::residual_nl_system(TrilinosWrappers::MPI::Vector &u).
template<int dim>
void ConstitutiveLaw<dim>::plast_linear_hardening(
SymmetricTensor<4, dim> &stress_strain_tensor,
// @sect3{ConstitutiveLaw::linearized_plast_linear_hardening}
-// This function returns the linearized stress strain tensor.
-// It contains the derivative of the nonlinear constitutive law.
+// This function returns the linearized stress strain tensor
+// in the solution $u^{i-1}$ of the previous Newton $i-1$ step.
+// The parameter strain_tensor $\varepsilon(u^{i-1})$ is calculated
+// by $u^{i-1}$. It contains the derivative of the nonlinear
+// constitutive law. As the result this function returns
+// the stress_strain_tensor of the nonlinear problem as well as
+// the stress_strain_tensor_linearized of the linearized problem.
+// See
+// PlasticityContactProblem::assemble_nl_system(TrilinosWrappers::MPI::Vector &u)
+// where this function is used.
template<int dim>
void ConstitutiveLaw<dim>::linearized_plast_linear_hardening(
SymmetricTensor<4, dim> &stress_strain_tensor_linearized,
if (component == 1)
return_value = 0.0;
if (component == 2)
- return_value = 0.0;//-26923.07692;
+ return_value = 0.0;
return return_value;
}
void
output_results(const std::string &title);
void
- output_for_benchmark(const unsigned int cycle);
+ output_contact_force(const unsigned int cycle);
double to_refine_factor;
double to_coarsen_factor;
FESystem<dim> fe;
DoFHandler<dim> dof_handler;
+ // We are using the SolutionTransfer class to interpolate the
+ // solution on the new refined mesh. It appears in th refine_grid()
+ // and the run() function.
std_cxx1x::shared_ptr<
parallel::distributed::SolutionTransfer<dim,
TrilinosWrappers::MPI::Vector> > soltrans;
move_mesh(tmp);
}
-// @sect4{PlasticityContactProblem::output_for_benchmark}
-
+// @sect4{PlasticityContactProblem::output_contact_force}
+
+// This function provides the contact force by calculating
+// an integral over the contact pressure in z-directions
+// over the contact area. For this purpose we set the contact
+// pressure lambda to 0 for all inactive dofs. For all
+// active dofs we lambda contains the quotient of the nonlinear
+// residual (resid_vector) and corresponding diagonal entry
+// of the mass matrix (diag_mass_matrix_vector). Because it is
+// not unlikely that hanging nodes shows up in the contact area
+// it is important to apply contraints_hanging_nodes.distribute
+// to the distributed_lambda vector.
+// To calculate the contact pressure in a certain point in the
+// contact area, we have make use of the Functions::FEFieldFunction
+// In parallel this is little tricky because we have to find the
+// process with the right cell which contains this point.
template<int dim>
-void PlasticityContactProblem<dim>::output_for_benchmark(
+void PlasticityContactProblem<dim>::output_contact_force(
const unsigned int cycle) {
Functions::FEFieldFunction<dim, DoFHandler<dim>,
TrilinosWrappers::MPI::Vector> solution_function(dof_handler,
typename DoFHandler<dim>::active_cell_iterator cell =
dof_handler.begin_active(), endc = dof_handler.end();
for (; cell != endc; ++cell)
- if (cell->is_locally_owned())
+ if (cell->is_locally_owned())
for (unsigned int face = 0;
face < GeometryInfo < dim > ::faces_per_cell; ++face)
if (cell->face(face)->at_boundary()
discrete equations yield very large linear systems very quickly, especially
for systems of equations in dim=2 or dim=3.
+<h4> Reducing the size of the linear system </h4>
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
solution process.
<li> Use the local element solutions to construct the global problem for the
trace values. These are the only globally coupled unknowns.
- <li> Modify the local solutions from the computed trace values.
+ <li> Reconstruct the local solutions from the computed trace values.
</ol>
+The above procedure also has a linear algebra interpretation and referred to
+as static condensation. Let us write the complete linear system associated to
+the HDG problem as a block system with the discrete DG variables <i>U</i> as
+first block and the skeleton variables $\Lambda$ as the second block:
+@f{eqnarray*}
+\begin{pmatrix} A & B \\ C & D \end{pmatrix}
+\begin{pmatrix} U \\ \Lambda \end{pmatrix}
+=
+\begin{pmatrix} F \\ G \end{pmatrix}
+@f}
+Our aim is now to eliminate the <i>U</i> block with a Schur complement
+approach similar to step-20, which results in the following two steps:
+@f{eqnarray*}
+(D - C A^{-1} B) \Lambda &=& G - C A^{-1} F \\
+A U &=& F - B \Lambda
+@f}
+The steps in the Dirichlet-to-Neumann map concept hence correspond to
+<ol>
+ <li> constructing the Schur complement matrix $D-C A^{-1} B$ and right hand side $G - C A^{-1} F$,
+ <li> solving the Schur complement system for $\Lambda$, and
+ <li> solving the equation for <i>U</i> using the second equation which uses $\Lambda$.
+</ol>
+
+The important ingredient from the linear algebra point of view is that the
+matrix <i>A</i> is block-diagonal with block size equal to the number of
+degrees of freedom of the interior DG variables which are always only related
+to a single cell. The coupling to other cells is introduced by the matrices
+<i>B</i> and <i>C</i> over the skeleton variable. The block-diagonality of
+<i>A</i> and the structure in <i>B</i> and <i>C</i> allow us to invert the
+matrix <i>A</i> element by element (the local solution of the Dirichelt
+problem) and subtract $CA^{-1}B$ from $D$.
+
+<h4> Solution quality and rates of convergence</h4>
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
+converge suboptimally. The local HDG solutions can be shown to converge
+as $\mathcal{O}(h^{p+1})$, i.e., at optimal order. 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})$.
@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
+cells dofs val L2 grad L2 val L2-post
+ 16 80 1.804e+01 2.207e+01 1.798e+01
+ 31 170 9.874e+00 1.322e+01 9.798e+00
+ 61 314 7.452e-01 3.793e+00 4.891e-01
+ 121 634 3.240e-01 1.511e+00 2.616e-01
+ 238 1198 8.585e-02 8.212e-01 1.808e-02
+ 454 2290 4.802e-02 5.178e-01 2.195e-02
+ 898 4378 2.561e-02 2.947e-01 4.318e-03
+ 1720 7864 1.306e-02 1.664e-01 2.978e-03
+ 3271 14638 7.025e-03 9.815e-02 1.075e-03
+ 6217 27214 4.119e-03 6.407e-02 9.975e-04
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
+cells dofs val L2 grad L2 val L2-post
+ 16 80 1.804e+01 - 2.207e+01 - 1.798e+01 -
+ 36 168 6.125e+00 2.66 9.472e+00 2.09 6.084e+00 2.67
+ 64 288 9.785e-01 6.38 4.260e+00 2.78 7.102e-01 7.47
+ 144 624 2.730e-01 3.15 1.866e+00 2.04 6.115e-02 6.05
+ 256 1088 1.493e-01 2.10 1.046e+00 2.01 2.880e-02 2.62
+ 576 2400 6.965e-02 1.88 4.846e-01 1.90 9.204e-03 2.81
+ 1024 4224 4.018e-02 1.91 2.784e-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
+ 9216 37248 4.690e-03 1.97 3.228e-02 1.97 1.599e-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
+cells dofs val L2 grad L2 val L2-post
+ 16 160 3.613e-01 - 1.891e+00 - 3.020e-01 -
+ 36 336 6.411e-02 4.26 5.081e-01 3.24 3.238e-02 5.51
+ 64 576 3.480e-02 2.12 2.533e-01 2.42 5.277e-03 6.31
+ 144 1248 8.297e-03 3.54 5.924e-02 3.58 6.330e-04 5.23
+ 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.277e-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.750e-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.788e-08 5.01
@endcode
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
+cells dofs val L2 grad L2 val L2-post
+ 8 144 7.122e+00 1.941e+01 6.102e+00
+ 29 500 3.309e+00 1.023e+01 2.145e+00
+ 113 1792 2.204e+00 1.023e+01 1.912e+00
+ 379 5732 6.085e-01 5.008e+00 2.233e-01
+ 1317 19412 1.543e-01 1.464e+00 4.196e-02
+ 4579 64768 5.058e-02 5.611e-01 9.521e-03
+ 14596 199552 2.129e-02 3.122e-01 4.569e-03
+ 46180 611400 1.033e-02 1.622e-01 1.684e-03
+144859 1864212 5.007e-03 8.371e-02 7.364e-04
+451060 5684508 2.518e-03 4.562e-02 3.070e-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
+cells dofs val L2 grad L2 val L2-post
+ 8 144 7.122e+00 - 1.941e+01 - 6.102e+00 -
+ 27 432 5.491e+00 0.64 2.184e+01 -0.29 4.448e+00 0.78
+ 64 960 3.646e+00 1.42 1.299e+01 1.81 3.306e+00 1.03
+ 216 3024 1.595e+00 2.04 8.550e+00 1.03 1.441e+00 2.05
+ 512 6912 6.922e-01 2.90 5.306e+00 1.66 2.511e-01 6.07
+ 1728 22464 2.915e-01 2.13 2.490e+00 1.87 8.588e-02 2.65
+ 4096 52224 1.684e-01 1.91 1.453e+00 1.87 4.055e-02 2.61
+ 13824 172800 7.972e-02 1.84 6.861e-01 1.85 1.335e-02 2.74
+ 32768 405504 4.637e-02 1.88 3.984e-01 1.89 5.932e-03 2.82
+110592 1354752 2.133e-02 1.92 1.830e-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
+cells dofs val L2 grad L2 val L2-post
+ 8 576 5.670e+00 - 1.868e+01 - 5.462e+00 -
+ 27 1728 1.048e+00 4.16 6.988e+00 2.42 8.011e-01 4.73
+ 64 3840 2.831e-01 4.55 2.710e+00 3.29 1.363e-01 6.16
+ 216 12096 7.883e-02 3.15 7.721e-01 3.10 2.158e-02 4.55
+ 512 27648 3.642e-02 2.68 3.305e-01 2.95 5.231e-03 4.93
+ 1728 89856 8.546e-03 3.58 7.581e-02 3.63 7.640e-04 4.74
+ 4096 208896 2.598e-03 4.14 2.313e-02 4.13 1.783e-04 5.06
+ 13824 691200 5.314e-04 3.91 4.697e-03 3.93 2.355e-05 4.99
+ 32768 1622016 1.723e-04 3.91 1.517e-03 3.93 5.602e-06 4.99
+110592 5419008 3.482e-05 3.94 3.055e-04 3.95 7.374e-07 5.00
@endcode
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
-#include <deal.II/lac/solver_gmres.h>
+#include <deal.II/lac/solver_bicgstab.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
for (unsigned int q=0; q<n_face_q_points; ++q)
{
const double JxW = scratch.fe_face_values.JxW(q);
+ const Point<dim> quadrature_point =
+ scratch.fe_face_values.quadrature_point(q);
const Point<dim> normal = scratch.fe_face_values.normal_vector(q);
const Tensor<1,dim> convection
- = scratch.convection_velocity.value(scratch.fe_face_values.quadrature_point(q));
+ = scratch.convection_velocity.value(quadrature_point);
const double tau_stab = (tau_stab_diffusion +
std::abs(convection * normal));
(cell->face(face)->boundary_indicator() == 1))
{
const double neumann_value =
- scratch.exact_solution.value(scratch.fe_face_values.quadrature_point(q));
+ - scratch.exact_solution.gradient (quadrature_point) * normal
+ + convection * normal * scratch.exact_solution.value(quadrature_point);
for (unsigned int i=0; i<scratch.fe_support_on_face[face].size(); ++i)
{
const unsigned int ii=scratch.fe_support_on_face[face][i];
- task_data.cell_vector(ii) -= scratch.tr_phi[i] * neumann_value * JxW;
+ task_data.cell_vector(ii) += scratch.tr_phi[i] * neumann_value * JxW;
}
}
}
{
const unsigned int ii=scratch.fe_local_support_on_face[face][i];
scratch.l_rhs(ii) -= (scratch.q_phi[i] * normal
- +
- scratch.u_phi[i] * (convection * normal - tau_stab)
- ) * scratch.trace_values[q] * JxW;
+ +
+ scratch.u_phi[i] * (convection * normal - tau_stab)
+ ) * scratch.trace_values[q] * JxW;
}
}
}
void Step51<dim>::solve ()
{
SolverControl solver_control (system_matrix.m()*10,
- 1e-10*system_rhs.l2_norm());
- SolverGMRES<> solver (solver_control, 50);
+ 1e-11*system_rhs.l2_norm());
+ SolverBicgstab<> solver (solver_control, false);
solver.solve (system_matrix, solution, system_rhs,
PreconditionIdentity());
- std::cout << " Number of GMRES iterations: " << solver_control.last_step()
+ std::cout << " Number of BiCGStab iterations: " << solver_control.last_step()
<< std::endl;
system_matrix.clear();
if (cycle == 0)
{
GridGenerator::subdivided_hyper_cube (triangulation, 2, -1, 1);
+ triangulation.refine_global(3-dim);
}
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);
+ triangulation.clear();
+ GridGenerator::subdivided_hyper_cube (triangulation, 2+(cycle%2), -1, 1);
+ triangulation.refine_global(3-dim+cycle/2);
break;
}
case adaptive_refinement:
- {
- Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
+ {
+ Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
- FEValuesExtractors::Scalar scalar(dim);
- typename FunctionMap<dim>::type neumann_boundary;
- KellyErrorEstimator<dim>::estimate (dof_handler_local,
- QGauss<dim-1>(3),
- neumann_boundary,
- solution_local,
- estimated_error_per_cell,
- fe_local.component_mask(scalar));
+ FEValuesExtractors::Scalar scalar(dim);
+ typename FunctionMap<dim>::type neumann_boundary;
+ KellyErrorEstimator<dim>::estimate (dof_handler_local,
+ QGauss<dim-1>(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.);
+ GridRefinement::refine_and_coarsen_fixed_number (triangulation,
+ estimated_error_per_cell,
+ 0.3, 0.);
- triangulation.execute_coarsening_and_refinement ();
+ triangulation.execute_coarsening_and_refinement ();
- break;
- }
+ break;
+ }
default:
- {
- Assert (false, ExcNotImplemented());
- }
+ {
+ Assert (false, ExcNotImplemented());
+ }
}
- }
+
+ // Just as in step-7, we set the boundary indicator of one of the faces to 1
+ // where we want to specify Neumann boundary conditions instead of Dirichlet
+ // conditions. Since we re-create the triangulation every time for global
+ // refinement, the flags are set in every refinement step, not just at the
+ // beginning.
+ typename Triangulation<dim>::cell_iterator
+ cell = triangulation.begin (),
+ endc = triangulation.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if ((std::fabs(cell->face(face)->center()(0) - (-1)) < 1e-12)
+ ||
+ (std::fabs(cell->face(face)->center()(1) - (-1)) < 1e-12))
+ cell->face(face)->set_boundary_indicator (1);
+}
{
public:
/**
- * Data structure describing a patch of
- * data in <tt>dim</tt> space
+ * Data structure describing a patch of data in <tt>dim</tt> space
* dimensions.
*
* A patch consists of the following data:
* <ul>
* <li>the corner #vertices,
- * <li> the number
- * #n_subdivisions of the number
- * of cells the Patch has in each
- * space direction,
- * <li> the #data attached to
- * each vertex, in the usual
+ * <li> the number #n_subdivisions of the number of cells the Patch
+ * has in each space direction,
+ * <li> the #data attached to each vertex, in the usual
* lexicographic ordering,
* <li> Information on #neighbors.
* </ul>
*
- * See the general
- * documentation of the
- * <tt>DataOutBase</tt> class for more
- * information on its contents and
- * purposes. In the case of two
- * dimensions, the next picture ist an
- * example of <tt>n_subdivision</tt> = 4
- * because the number of (sub)cells
- * within each patch is equal to
- * <tt>2^dim</tt>.
+ * See the general documentation of the DataOutBase class for more
+ * information on its contents and purposes. In the case of two
+ * dimensions, the next picture ist an example of
+ * <tt>n_subdivision</tt> = 4 because the number of (sub)cells
+ * within each patch is equal to <tt>2<sup>dim</sup></tt>.
*
* @ingroup output
*
struct Patch
{
/**
- * Make the <tt>spacedim</tt> template
- * parameter available.
+ * Make the <tt>spacedim</tt> template parameter available.
*/
static const unsigned int space_dim=spacedim;
/**
- * Corner points of a patch.
- * Inner points are computed by
- * a multilinear transform of
- * the unit cell to the cell
- * specified by these corner
- * points. The order of points
- * is the same as for cells
- * in the triangulation.
+ * Corner points of a patch. Inner points are computed by a
+ * multilinear transform of the unit cell to the cell specified by
+ * these corner points. The order of points is the same as for
+ * cells in the triangulation.
*/
Point<spacedim> vertices[GeometryInfo<dim>::vertices_per_cell];
/**
- * Numbers of neighbors of a patch.
- * OpenDX format requires
- * neighbor information for
- * advanced output. Here the
- * neighborship relationship
- * of patches is
- * stored. During output,
- * this must be transformed
- * into neighborship of
- * sub-grid cells.
+ * Numbers of neighbors of a patch. OpenDX format requires
+ * neighbor information for advanced output. Here the neighborship
+ * relationship of patches is stored. During output, this must be
+ * transformed into neighborship of sub-grid cells.
*/
unsigned int neighbors[dim > 0
?
1];
/**
- * Number of this
- * patch. Since we are not
- * sure patches are handled
- * in the same order, always,
- * we better store this.
+ * Number of this patch. Since we are not sure patches are handled
+ * in the same order, always, we better store this.
*/
unsigned int patch_index;
/**
- * Number of subdivisions with
- * which this patch is to be
- * written. <tt>1</tt> means no
- * subdivision, <tt>2</tt> means
- * bisection, <tt>3</tt> trisection,
- * etc.
+ * Number of subdivisions with which this patch is to be
+ * written. <tt>1</tt> means no subdivision, <tt>2</tt> means
+ * bisection, <tt>3</tt> trisection, etc.
*/
unsigned int n_subdivisions;
/**
- * Data vectors. The format is
- * as follows:
- * <tt>data(i,.)</tt> denotes the data
- * belonging to the <tt>i</tt>th data
- * vector. <tt>data.n()</tt>
- * therefore equals the number
- * of output points; this
- * number is <tt>(subdivisions+1)^{dim</tt>}.
- * <tt>data.m()</tt> equals the number of
- * data vectors.
+ * Data vectors. The format is as follows: <tt>data(i,.)</tt>
+ * denotes the data belonging to the <tt>i</tt>th data
+ * vector. <tt>data.n()</tt> therefore equals the number of output
+ * points; this number is <tt>(subdivisions+1)^{dim</tt>}.
+ * <tt>data.m()</tt> equals the number of data vectors.
*
- * Within each column,
- * <tt>data(.,j)</tt> are the
- * data values at the output
- * point <tt>j</tt>, where
- * <tt>j</tt> denotes the
- * usual lexicographic
- * ordering in deal.II. This
- * is also the order of
- * points as provided by the
- * <tt>QIterated</tt> class
- * when used with the
- * <tt>QTrapez</tt> class as
- * subquadrature.
+ * Within each column, <tt>data(.,j)</tt> are the data values at
+ * the output point <tt>j</tt>, where <tt>j</tt> denotes the usual
+ * lexicographic ordering in deal.II. This is also the order of
+ * points as provided by the <tt>QIterated</tt> class when used
+ * with the <tt>QTrapez</tt> class as subquadrature.
*
- * Since the number of data vectors
- * is usually the same for all
- * patches to be printed,
- * <tt>data.size()</tt> should yield
- * the same value for all patches
- * provided. The exception are
- * patches for which
- * points_are_available are set,
- * where the actual coordinates of
- * the point are appended to the
- * 'data' field, see the
- * documentation of the
- * points_are_available flag.
+ * Since the number of data vectors is usually the same for all
+ * patches to be printed, <tt>data.size()</tt> should yield the
+ * same value for all patches provided. The exception are patches
+ * for which points_are_available are set, where the actual
+ * coordinates of the point are appended to the 'data' field, see
+ * the documentation of the points_are_available flag.
*/
Table<2,float> data;
/**
- * Bool flag indicating, whether the
- * coordinates of the inner patch
- * points are appended to the @p data
- * table (@ true) or not (@ false),
- * where the second is the standard and
- * can be found for all cells in the
- * interior of a domain.
+ * Bool flag indicating, whether the coordinates of the inner
+ * patch points are appended to the @p data table (@p true) or not
+ * (@p false), where the second is the standard and can be found
+ * for all cells in the interior of a domain.
*
- * On the boundary of a domain, patch
- * points are evaluated using a
- * Mapping and therefore have to be
- * stored inside the patch, as the
- * Mapping and the corresponding
- * boundary information are no longer
- * available later on when we
- * actually write the patch out to an
- * output stream.
+ * On the boundary of a domain, patch points are evaluated using a
+ * Mapping and therefore have to be stored inside the patch, as
+ * the Mapping and the corresponding boundary information are no
+ * longer available later on when we actually write the patch out
+ * to an output stream.
*/
bool points_are_available;
/**
- * Default constructor. Sets
- * <tt>n_subdivisions</tt> to one.
+ * Default constructor. Sets #n_subdivisions to one.
*/
Patch ();
/**
- * Compare the present patch
- * for equality with another
- * one. This is used in a few
- * of the automated tests in
- * our testsuite.
+ * Compare the present patch for equality with another one. This
+ * is used in a few of the automated tests in our testsuite.
*/
bool operator == (const Patch &patch) const;
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
/**
- * Value to be used if this
- * patch has no neighbor on
- * one side.
+ * Value to be used if this patch has no neighbor on one side.
*/
static const unsigned int no_neighbor = numbers::invalid_unsigned_int;
/** @addtogroup Exceptions
};
/**
- * Flags controlling the details of
- * output in OpenDX format.
+ * Flags controlling the details of output in OpenDX format.
*
* @ingroup output
*/
struct DXFlags
{
/**
- * Write neighbor
- * information. This
- * information is necessary
- * for instance, if OpenDX is
- * supposed to compute
- * integral curves
- * (streamlines). If it is
- * not present, streamlines
- * end at cell boundaries.
+ * Write neighbor information. This information is necessary for
+ * instance, if OpenDX is supposed to compute integral curves
+ * (streamlines). If it is not present, streamlines end at cell
+ * boundaries.
*/
bool write_neighbors;
/**
- * Write integer values of
- * the Triangulation in
- * binary format.
+ * Write integer values of the Triangulation in binary format.
*/
bool int_binary;
/**
- * Write coordinate vectors in
- * binary format.
+ * Write coordinate vectors in binary format.
*/
bool coordinates_binary;
/**
- * Write data vectors in
- * binary format.
+ * Write data vectors in binary format.
*/
bool data_binary;
/**
- * Write binary coordinate
- * vectors as double (64 bit)
- * numbers instead of float (32 bit).
+ * Write binary coordinate vectors as double (64 bit) numbers
+ * instead of float (32 bit).
*/
bool data_double;
const bool data_binary = false);
/**
- * Declare all flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare all flags with name and type as offered by this class,
+ * for use in input files.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and set
+ * the flags for this output format accordingly.
*
- * The flags thus obtained overwrite
- * all previous contents of this object.
+ * The flags thus obtained overwrite all previous contents of this
+ * object.
*/
void parse_parameters (const ParameterHandler &prm);
/**
- * 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;
};
/**
- * Flags controlling the details
- * of output in UCD format for
- * AVS.
+ * Flags controlling the details of output in UCD format for AVS.
*
* @ingroup output
*/
struct UcdFlags
{
/**
- * Write a comment at the
- * beginning of the file
- * stating the date of
- * creation and some other
- * data. While this is
- * supported by the UCD
- * format and
- * AVS, some other
- * programs get confused by
- * this, so the default is to
- * not write a
- * preamble. However, a
- * preamble can be written
- * using this flag.
+ * Write a comment at the beginning of the file stating the date
+ * of creation and some other data. While this is supported by
+ * the UCD format and AVS, some other programs get confused by
+ * this, so the default is to not write a preamble. However, a
+ * preamble can be written using this flag.
*
* Default: <code>false</code>.
*/
UcdFlags (const bool write_preamble = false);
/**
- * Declare all flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare all flags with name and type as offered by this class,
+ * for use in input files.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and
+ * set the flags for this output format accordingly.
*
- * The flags thus obtained overwrite
- * all previous contents of this object.
+ * The flags thus obtained overwrite all previous contents of this
+ * object.
*/
void parse_parameters (const ParameterHandler &prm);
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
};
/**
- * Flags controlling the details of
- * output in Gnuplot format. At
+ * Flags controlling the details of output in Gnuplot format. At
* present no flags are implemented.
*
* @ingroup output
{
private:
/**
- * Dummy entry to suppress compiler
- * warnings when copying an empty
- * structure. Remove this member
- * when adding the first flag to
- * this structure (and remove the
- * <tt>private</tt> as well).
+ * Dummy entry to suppress compiler warnings when copying an empty
+ * structure. Remove this member when adding the first flag to
+ * this structure (and remove the <tt>private</tt> as well).
*/
int dummy;
GnuplotFlags ();
/**
- * Declare all flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare all flags with name and type as offered by this class,
+ * for use in input files.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and set
+ * the flags for this output format accordingly.
*
- * The flags thus obtained overwrite
- * all previous contents of this object.
+ * The flags thus obtained overwrite all previous contents of this
+ * object.
*/
void parse_parameters (const ParameterHandler &prm) const;
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
};
/**
- * Flags controlling the details
- * of output in Povray
- * format. Several flags are
- * implemented, see their
- * respective documentation.
+ * Flags controlling the details of output in Povray format. Several
+ * flags are implemented, see their respective documentation.
*
* @ingroup output
*/
struct PovrayFlags
{
/**
- * Normal vector interpolation,
- * if set to true
+ * Normal vector interpolation, if set to true
*
* default = false
*/
bool smooth;
/**
- * Use bicubic patches (b-splines)
- * instead of triangles.
+ * Use bicubic patches (b-splines) instead of triangles.
*
* default = false
*/
bool bicubic_patch;
/**
- * include external "data.inc"
- * with camera, light and
- * texture definition for the
- * scene.
+ * include external "data.inc" with camera, light and texture
+ * definition for the scene.
*
* default = false
*/
const bool external_data = false);
/**
- * Declare all flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare all flags with name and type as offered by this class,
+ * for use in input files.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and
+ * set the flags for this output format accordingly.
*
- * The flags thus obtained overwrite
- * all previous contents of this object.
+ * The flags thus obtained overwrite all previous contents of this
+ * object.
*/
void parse_parameters (const ParameterHandler &prm);
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
};
/**
- * Flags controlling the details of
- * output in encapsulated postscript
- * format.
+ * Flags controlling the details of output in encapsulated
+ * postscript format.
*
* @ingroup output
*/
struct EpsFlags
{
/**
- * This denotes the number of the
- * data vector which shall be used
- * for generating the height
- * information. By default, the
- * first data vector is taken,
- * i.e. <tt>height_vector==0</tt>, if
- * there is any data vector. If there
- * is no data vector, no height
+ * This denotes the number of the data vector which shall be used
+ * for generating the height information. By default, the first
+ * data vector is taken, i.e. <tt>height_vector==0</tt>, if there
+ * is any data vector. If there is no data vector, no height
* information is generated.
*/
unsigned int height_vector;
/**
- * Number of the vector which is
- * to be taken to colorize cells.
- * The same applies as for
- * <tt>height_vector</tt>.
+ * Number of the vector which is to be taken to colorize cells.
+ * The same applies as for #height_vector.
*/
unsigned int color_vector;
/**
- * Enum denoting the possibilities
- * whether the scaling should be done
- * such that the given <tt>size</tt> equals
- * the width or the height of
- * the resulting picture.
+ * Enum denoting the possibilities whether the scaling should be
+ * done such that the given <tt>size</tt> equals the width or the
+ * height of the resulting picture.
*/
enum SizeType
{
SizeType size_type;
/**
- * Width or height of the output
- * as given in postscript units
- * This usually is given by the
- * strange unit 1/72 inch. Whether
- * this is height or width is
- * specified by the flag
- * <tt>size_type</tt>.
+ * Width or height of the output as given in postscript units This
+ * usually is given by the strange unit 1/72 inch. Whether this is
+ * height or width is specified by the flag <tt>size_type</tt>.
*
- * Default is 300, which represents
- * a size of roughly 10 cm.
+ * Default is 300, which represents a size of roughly 10 cm.
*/
unsigned int size;
/**
- * Width of a line in postscript
- * units. Default is 0.5.
+ * Width of a line in postscript units. Default is 0.5.
*/
double line_width;
/**
- * Angle of the line origin-viewer
- * against the z-axis in degrees.
+ * Angle of the line origin-viewer against the z-axis in degrees.
*
- * Default is the Gnuplot-default
- * of 60.
+ * Default is the Gnuplot-default of 60.
*/
double azimut_angle;
/**
- * Angle by which the viewers
- * position projected onto the
- * x-y-plane is rotated around
- * the z-axis, in positive sense
- * when viewed from above. The
- * unit are degrees, and zero
- * equals a position above or below
- * the negative y-axis.
+ * Angle by which the viewers position projected onto the
+ * x-y-plane is rotated around the z-axis, in positive sense when
+ * viewed from above. The unit are degrees, and zero equals a
+ * position above or below the negative y-axis.
*
- * Default is the
- * Gnuplot-default of 30.
- * An example of a
- * Gnuplot-default of 0 is
- * the following:
+ * Default is the Gnuplot-default of 30. An example of a
+ * Gnuplot-default of 0 is the following:
*
* @verbatim
*
double turn_angle;
/**
- * Factor by which the z-axis is to
- * be stretched as compared to the
- * x- and y-axes. This is to compensate
- * for the different sizes that
- * coordinate and solution values may
- * have and to prevent that the plot
- * looks to much out-of-place (no
- * elevation at all if solution values
- * are much smaller than coordinate
- * values, or the common "extremely
- * mountainous area" in the opposite
- * case.
+ * Factor by which the z-axis is to be stretched as compared to
+ * the x- and y-axes. This is to compensate for the different
+ * sizes that coordinate and solution values may have and to
+ * prevent that the plot looks to much out-of-place (no elevation
+ * at all if solution values are much smaller than coordinate
+ * values, or the common "extremely mountainous area" in the
+ * opposite case.
*
* Default is <tt>1.0</tt>.
*/
double z_scaling;
/**
- * Flag the determines whether the
- * lines bounding the cells (or the
- * parts of each patch) are to be
- * plotted.
+ * Flag the determines whether the lines bounding the cells (or
+ * the parts of each patch) are to be plotted.
*
* Default: <tt>true</tt>.
*/
bool draw_mesh;
/**
- * Flag whether to fill the regions
- * between the lines bounding the cells
- * or not. If not, no hidden line removal
- * is performed, which in this crude
- * implementation is done through
- * writing the cells in a back-to-front
- * order, thereby hiding the cells in
- * the background by cells in the
- * foreground.
+ * Flag whether to fill the regions between the lines bounding the
+ * cells or not. If not, no hidden line removal is performed,
+ * which in this crude implementation is done through writing the
+ * cells in a back-to-front order, thereby hiding the cells in the
+ * background by cells in the foreground.
*
- * If this flag is <tt>false</tt> and <tt>draw_mesh</tt>
- * is <tt>false</tt> as well, nothing will be
- * printed.
+ * If this flag is <tt>false</tt> and #draw_mesh is <tt>false</tt>
+ * as well, nothing will be printed.
*
- * If this flag is <tt>true</tt>, then the cells
- * will be drawn either colored by one
- * of the data sets (if <tt>shade_cells</tt> is
- * <tt>true</tt>), or pure white (if
- * <tt>shade_cells</tt> is false or if there are
- * no data sets).
+ * If this flag is <tt>true</tt>, then the cells will be drawn
+ * either colored by one of the data sets (if #shade_cells is
+ * <tt>true</tt>), or pure white (if #shade_cells is false or if
+ * there are no data sets).
*
* Default is <tt>true</tt>.
*/
bool draw_cells;
/**
- * Flag to determine whether the cells
- * shall be colorized by the data
- * set denoted by <tt>color_vector</tt>, or
- * simply be painted in white. This
- * flag only makes sense if
- * <tt>draw_cells==true</tt>. Colorization is
- * done through the <tt>color_function</tt>.
+ * Flag to determine whether the cells shall be colorized by the
+ * data set denoted by #color_vector, or simply be painted in
+ * white. This flag only makes sense if
+ * <tt>#draw_cells==true</tt>. Colorization is done through
+ * #color_function.
*
* Default is <tt>true</tt>.
*/
bool shade_cells;
/**
- * Structure keeping the three color
- * values in the RGB system.
+ * Structure keeping the three color values in the RGB system.
*/
struct RgbValues
{
float blue;
/**
- * Return <tt>true</tt> if the
- * color represented by
- * the three color values
- * is a grey scale,
- * i.e. all components
- * are equal.
+ * Return <tt>true</tt> if the color represented by the three
+ * color values is a grey scale, i.e. all components are equal.
*/
bool is_grey () const;
};
/**
- * Definition of a function pointer
- * type taking a value and returning
- * a triple of color values in RGB
- * values.
+ * Definition of a function pointer type taking a value and
+ * returning a triple of color values in RGB values.
*
- * Besides the actual value by which
- * the color is to be computed, min
- * and max values of the data to
- * be colorized are given as well.
+ * Besides the actual value by which the color is to be computed,
+ * min and max values of the data to be colorized are given as
+ * well.
*/
typedef RgbValues (*ColorFunction) (const double value,
const double min_value,
const double max_value);
/**
- * This is a pointer to the function
- * which is used to colorize the cells.
- * By default, it points to the
- * static function <tt>default_color_function</tt>
- * which is a member of this class.
+ * This is a pointer to the function which is used to colorize the
+ * cells. By default, it points to the static function
+ * default_color_function() which is a member of this class.
*/
ColorFunction color_function;
/**
- * Default colorization function. This
- * one does what one usually wants:
- * It shifts colors from black (lowest
- * value) through blue, green and red
- * to white (highest value). For the
- * exact defition of the color scale
- * refer to the implementation.
+ * Default colorization function. This one does what one usually
+ * wants: It shifts colors from black (lowest value) through blue,
+ * green and red to white (highest value). For the exact defition
+ * of the color scale refer to the implementation.
*
- * This function was originally written
- * by Stefan Nauber.
+ * This function was originally written by Stefan Nauber.
*/
static RgbValues
default_color_function (const double value,
const double max_value);
/**
- * This is an alternative color
- * function producing a grey scale
- * between black (lowest values)
- * and white (highest values). You
- * may use it by setting the
- * <tt>color_function</tt> variable to the
+ * This is an alternative color function producing a grey scale
+ * between black (lowest values) and white (highest values). You
+ * may use it by setting the #color_function variable to the
* address of this function.
*/
static RgbValues
const double max_value);
/**
- * This is one more
- * alternative color function
- * producing a grey scale
- * between white (lowest
- * values) and black (highest
- * values), i.e. the scale is
- * reversed to the previous
- * one. You may use it by
- * setting the
- * <tt>color_function</tt>
- * variable to the address of
- * this function.
+ * This is one more alternative color function producing a grey
+ * scale between white (lowest values) and black (highest values),
+ * i.e. the scale is reversed to the previous one. You may use it
+ * by setting the #color_function variable to the address of this
+ * function.
*/
static RgbValues
reverse_grey_scale_color_function (const double value,
const ColorFunction color_function= &default_color_function);
/**
- * Declare all flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare all flags with name and type as offered by this class,
+ * for use in input files.
*
- * For coloring, only the color
- * functions declared in this
- * class are offered.
+ * For coloring, only the color functions declared in this class
+ * are offered.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and set
+ * the flags for this output format accordingly.
*
- * The flags thus obtained overwrite
- * all previous contents of this object.
+ * The flags thus obtained overwrite all previous contents of this
+ * object.
*/
void parse_parameters (const ParameterHandler &prm);
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
};
/**
- * Flags controlling the details
- * of output in GMV
- * format. At present no flags
- * are implemented.
+ * Flags controlling the details of output in GMV format. At present
+ * no flags are implemented.
*
* @ingroup output
*/
{
private:
/**
- * Dummy entry to suppress compiler
- * warnings when copying an empty
- * structure. Remove this member
- * when adding the first flag to
- * this structure (and remove the
- * <tt>private</tt> as well).
+ * Dummy entry to suppress compiler warnings when copying an empty
+ * structure. Remove this member when adding the first flag to
+ * this structure (and remove the <tt>private</tt> as well).
*/
int dummy;
GmvFlags ();
/**
- * Declare all flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare all flags with name and type as offered by this class,
+ * for use in input files.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and set
+ * the flags for this output format accordingly.
*
- * The flags thus obtained overwrite
- * all previous contents of this object.
+ * The flags thus obtained overwrite all previous contents of this
+ * object.
*/
void parse_parameters (const ParameterHandler &prm) const;
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
};
/**
- * Flags controlling the details
- * of output in
- * Tecplot format.
+ * Flags controlling the details of output in Tecplot format.
*
* @ingroup output
*/
public:
/**
- * This variable is needed to hold the
- * output file name when using the
- * Tecplot API to write binary files.
- * If the user doesn't set the file
- * name with this variable only
- * ASCII Tecplot output will be
- * produced.
+ * This variable is needed to hold the output file name when using
+ * the Tecplot API to write binary files. If the user doesn't set
+ * the file name with this variable only ASCII Tecplot output will
+ * be produced.
*/
const char *tecplot_binary_file_name;
/**
- * Tecplot allows to assign
- * names to zones. This
- * variable stores this name.
+ * Tecplot allows to assign names to zones. This variable stores
+ * this name.
*/
const char *zone_name;
const char *zone_name = NULL);
/**
- * Declare all flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare all flags with name and type as offered by this class,
+ * for use in input files.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and set
+ * the flags for this output format accordingly.
*
- * The flags thus obtained overwrite
- * all previous contents of this object.
+ * The flags thus obtained overwrite all previous contents of this
+ * object.
*/
void parse_parameters (const ParameterHandler &prm) const;
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
};
/**
- * Flags controlling the details
- * of output in VTK
- * format.
+ * Flags controlling the details of output in VTK format.
*
* @ingroup output
*/
{
public:
/**
- * The time of the time step if this file is part of a
- * time dependent simulation.
+ * The time of the time step if this file is part of a time
+ * dependent simulation.
*
- * The value of this variable is written into the output file according
- * to the instructions provided in
+ * The value of this variable is written into the output file
+ * according to the instructions provided in
* http://www.visitusers.org/index.php?title=Time_and_Cycle_in_VTK_files
- * unless it is at its default value of std::numeric_limits<double>::min().
+ * unless it is at its default value of
+ * std::numeric_limits<double>::min().
*/
double time;
/**
- * The number of the time step if this file is part of a
- * time dependent simulation, or the cycle within a nonlinear or other
+ * The number of the time step if this file is part of a time
+ * dependent simulation, or the cycle within a nonlinear or other
* iteration.
*
- * The value of this variable is written into the output file according
- * to the instructions provided in
+ * The value of this variable is written into the output file
+ * according to the instructions provided in
* http://www.visitusers.org/index.php?title=Time_and_Cycle_in_VTK_files
- * unless it is at its default value of std::numeric_limits<unsigned int>::min().
+ * unless it is at its default value of
+ * std::numeric_limits<unsigned int>::min().
*/
unsigned int cycle;
/**
- * Flag to determine whether the current
- * date and time shall be printed as a comment
- * in the file's second line.
+ * Flag to determine whether the current date and time shall be
+ * printed as a comment in the file's second line.
*
* Default is <tt>true</tt>.
*/
const bool print_date_and_time = true);
/**
- * Declare the flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare the flags with name and type as offered by this class,
+ * for use in input files.
*
* Unlike the flags in many of the other classes similar to this one, we do
* not actually declare parameters for the #cycle and #time member variables
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and
+ * set the flags for this output format accordingly.
*
- * The flags thus obtained overwrite
- * all previous contents of this object.
+ * The flags thus obtained overwrite all previous contents of this
+ * object.
*/
void parse_parameters (const ParameterHandler &prm) const;
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
};
struct SvgFlags
{
public:
- /**
- * This denotes the number of the
- * data vector which shall be used
- * for generating the height
- * information. By default, the
- * first data vector is taken,
- * i.e. <tt>height_vector==0</tt>, if
- * there is any data vector. If there
- * is no data vector, no height
+ /**
+ * Height of the image in SVG
+ * units. Default value is 4000.
+ */
+ unsigned int height;
+
+ /**
+ * Width of the image in SVG
+ units. If left zero, the width is computed from the height.
+ */
+ unsigned int width;
+
+ /**
+ * This denotes the number of the data vector which shall be used
+ * for generating the height information. By default, the first
+ * data vector is taken, i.e. <tt>#height_vector==0</tt>, if there
+ * is any data vector. If there is no data vector, no height
* information is generated.
*/
- unsigned int height_vector;
-
- /*
+ unsigned int height_vector;
+
+ /**
* Angles for the perspective view
*/
int azimuth_angle, polar_angle;
unsigned int line_thickness;
- /*
+ /**
* Draw a margin of 5% around the plotted area
*/
bool margin;
- /*
+ /**
* Draw a colorbar encoding the cell coloring
*/
bool draw_colorbar;
- /*
+ /**
* Constructor.
*/
SvgFlags(const unsigned int height_vector = 0,
const bool draw_colorbar = true);
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
/**
- * Flags controlling the details
- * of output in deal.II
- * intermediate format. At
- * present no flags are
- * implemented.
+ * Flags controlling the details of output in deal.II intermediate
+ * format. At present no flags are implemented.
*
* @ingroup output
*/
struct Deal_II_IntermediateFlags
{
/**
- * An indicator of the
- * currect file format
- * version used to write
- * intermediate format. We do
- * not attempt to be backward
- * compatible, so this number
- * is used only to verify
- * that the format we are
- * writing is what the
- * current readers and
- * writers understand.
+ * An indicator of the currect file format version used to write
+ * intermediate format. We do not attempt to be backward
+ * compatible, so this number is used only to verify that the
+ * format we are writing is what the current readers and writers
+ * understand.
*/
static const unsigned int format_version = 3;
private:
/**
- * Dummy entry to suppress compiler
- * warnings when copying an empty
- * structure. Remove this member
- * when adding the first flag to
- * this structure (and remove the
- * <tt>private</tt> as well).
+ * Dummy entry to suppress compiler warnings when copying an empty
+ * structure. Remove this member when adding the first flag to
+ * this structure (and remove the <tt>private</tt> as well).
*/
int dummy;
Deal_II_IntermediateFlags ();
/**
- * Declare all flags with name
- * and type as offered by this
- * class, for use in input files.
+ * Declare all flags with name and type as offered by this class,
+ * for use in input files.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared in
- * <tt>declare_parameters</tt> and set the
- * flags for this output format
- * accordingly.
+ * Read the parameters declared in declare_parameters() and
+ * set the flags for this output format accordingly.
*
* The flags thus obtained overwrite
* all previous contents of this object.
void parse_parameters (const ParameterHandler &prm) const;
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
};
/**
- * Provide a data type specifying
- * the presently supported output
+ * Provide a data type specifying the presently supported output
* formats.
*/
enum OutputFormat
{
/**
- * Use the format already
- * stored in the object.
+ * Use the format already stored in the object.
*/
default_format,
/**
*/
dx,
/**
- * Output in the UCD format
- * for AVS.
+ * Output in the UCD format for AVS.
*/
ucd,
/**
- * Output for the
- * Gnuplot tool.
+ * Output for the Gnuplot tool.
*/
gnuplot,
/**
- * Output for the
- * Povray
- * raytracer.
+ * Output for the Povray raytracer.
*/
povray,
/**
- * Output in encapsulated
- * PostScript.
+ * Output in encapsulated PostScript.
*/
eps,
/**
*/
gmv,
/**
- * Output for
- * Tecplot in text
- * format.
+ * Output for Tecplot in text format.
*/
tecplot,
/**
- * Output for
- * Tecplot in
- * binary format. Faster
- * and smaller than text
- * format.
+ * Output for Tecplot in binary format. Faster and smaller than
+ * text format.
*/
tecplot_binary,
/**
- * Output in
- * VTK format.
+ * Output in VTK format.
*/
vtk,
/**
- * Output in
- * VTK format.
+ * Output in VTK format.
*/
vtu,
/**
- * Output in
- * SVG format.
+ * Output in SVG format.
*/
svg,
/**
- * Output in deal.II
- * intermediate format.
+ * Output in deal.II intermediate format.
*/
deal_II_intermediate,
/**
- * Output in
- * HDF5 format.
+ * Output in HDF5 format.
*/
hdf5
};
/**
- * Write the given list of patches to the output stream in
- * OpenDX format.
+ * Write the given list of patches to the output stream in OpenDX
+ * format.
*
* Since OpenDX uses some kind of visual data flow oriented
* programming language, some of these programs are provided in
* Write the given list of patches to the output stream in eps format.
*
* Output in this format circumvents the use of auxiliary graphic
- * programs converting some output format into a graphics format. This
- * has the advantage that output is easy and fast, and the
- * disadvantage that you have to give a whole bunch of parameters
- * which determine the direction of sight, the mode of colorization,
- * the scaling of the height axis, etc. (Of course, all these
- * parameters have reasonable default values, which you may want to
- * change from time to time.) At present, this format only supports
- * output for two-dimensional data, with values in the third direction
- * taken from a data vector.
+ * programs converting some output format into a graphics
+ * format. This has the advantage that output is easy and fast, and
+ * the disadvantage that you have to give a whole bunch of
+ * parameters which determine the direction of sight, the mode of
+ * colorization, the scaling of the height axis, etc. (Of course,
+ * all these parameters have reasonable default values, which you
+ * may want to change from time to time.) At present, this format
+ * only supports output for two-dimensional data, with values in the
+ * third direction taken from a data vector.
*
* Basically, output consists of the mesh and the cells in between
* them. You can draw either of these, or both, or none if you are
MPI_Comm comm);
/**
- * Given an input stream that contains
- * data written by
- * write_deal_II_intermediate, determine
- * the <tt>dim</tt> and <tt>spacedim</tt>
- * template parameters with which that
- * function was called, and return them
- * as a pair of values.
+ * Given an input stream that contains data written by
+ * write_deal_II_intermediate(), determine the <tt>dim</tt> and
+ * <tt>spacedim</tt> template parameters with which that function
+ * was called, and return them as a pair of values.
*
- * Note that this function eats a number
- * of elements at the present position of
- * the stream, and therefore alters
- * it. In order to read from it using,
- * for example, the DataOutReader class,
- * you may wish to either reset the
- * stream to its previous position, or
- * close and reopen it.
+ * Note that this function eats a number of elements at the present
+ * position of the stream, and therefore alters it. In order to read
+ * from it using, for example, the DataOutReader class, you may wish
+ * to either reset the stream to its previous position, or close and
+ * reopen it.
*/
static
std::pair<unsigned int, unsigned int>
determine_intermediate_format_dimensions (std::istream &input);
/**
- * Return the <tt>OutputFormat</tt>
- * value corresponding to the
- * given string. If the string
- * does not match any known
- * format, an exception is
- * thrown.
- *
- * Since this function does not
- * need data from this object, it
- * is static and can thus be
- * called without creating an
- * object of this class. Its main
- * purpose is to allow a program
- * to use any implemented output
- * format without the need to
- * extend the program's parser
- * each time a new format is
- * implemented.
- *
- * To get a list of presently
- * available format names,
- * e.g. to give it to the
- * ParameterHandler class,
- * use the function
+ * Return the OutputFormat value corresponding to the given
+ * string. If the string does not match any known format, an
+ * exception is thrown.
+ *
+ * Since this function does not need data from this object, it is
+ * static and can thus be called without creating an object of this
+ * class. Its main purpose is to allow a program to use any
+ * implemented output format without the need to extend the
+ * program's parser each time a new format is implemented.
+ *
+ * To get a list of presently available format names, e.g. to give
+ * it to the ParameterHandler class, use the function
* get_output_format_names().
*/
static OutputFormat parse_output_format (const std::string &format_name);
/**
- * Return a list of implemented
- * output formats. The different
- * names are separated by
- * vertical bar signs (<tt>`|'</tt>)
- * as used by the
+ * Return a list of implemented output formats. The different names
+ * are separated by vertical bar signs (<tt>`|'</tt>) as used by the
* ParameterHandler classes.
*/
static std::string get_output_format_names ();
/**
- * Provide a function which tells us which
- * suffix a file with a given output format
- * usually has. At present the following
- * formats are defined:
+ * Provide a function which tells us which suffix a file with a
+ * given output format usually has. At present the following formats
+ * are defined:
* <ul>
* <li> <tt>dx</tt>: <tt>.dx</tt>
* <li> <tt>ucd</tt>: <tt>.inp</tt>
static std::string default_suffix (const OutputFormat output_format);
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
static std::size_t memory_consumption ();
<< "The number of points in this data set is " << arg1
<< ", but we expected " << arg2 << " in each space direction.");
/**
- * An output function did not
- * receive any patches for
- * writing.
+ * An output function did not receive any patches for writing.
*/
DeclException0 (ExcNoPatches);
/**
//@}
private:
/**
- * Write the coordinates of nodes
- * in the desired format.
+ * Write the coordinates of nodes in the desired format.
*/
template <int dim, int spacedim, typename STREAM>
static void write_nodes (const std::vector<Patch<dim,spacedim> > &patches,
STREAM &out);
/**
- * Write the node numbers of a
- * cell in the desired format.
+ * Write the node numbers of a cell in the desired format.
*/
template <int dim, int spacedim, typename STREAM>
static void write_cells (const std::vector<Patch<dim,spacedim> > &patches,
STREAM &out);
/**
- * Write data in the desired
- * format.
+ * Write data in the desired format.
*/
template <int dim, int spacedim, class STREAM>
static void write_data (const std::vector<Patch<dim,spacedim> > &patches,
Point<3> camera_horizontal,
float camera_focus);
/**
- * Function to compute the gradient parameters for
- * a triangle with given values for the vertices.
+ * Function to compute the gradient parameters for a triangle with
+ * given values for the vertices.
*
* Used for svg output.
*/
/**
* Class holding the data of one cell of a patch in two space
* dimensions for output. It is the projection of a cell in
- * three-dimensional space (two coordinates, one height value)
- * to the direction of sight.
+ * three-dimensional space (two coordinates, one height value) to
+ * the direction of sight.
*/
class SvgCell
{
Point<3> vertices[4];
/**
- * Depth into the picture, which
- * is defined as the distance from
- * an observer at an the origin in
- * direction of the line of sight.
+ * Depth into the picture, which is defined as the distance from
+ * an observer at an the origin in direction of the line of sight.
*/
float depth;
Point<2> projected_center;
/**
- * Comparison operator for
- * sorting.
+ * Comparison operator for sorting.
*/
bool operator < (const SvgCell &) const;
};
/**
- * Class holding the data of one
- * cell of a patch in two space
- * dimensions for output. It is
- * the projection of a cell in
- * three-dimensional space (two
- * coordinates, one height value)
- * to the direction of sight.
+ * Class holding the data of one cell of a patch in two space
+ * dimensions for output. It is the projection of a cell in
+ * three-dimensional space (two coordinates, one height value) to
+ * the direction of sight.
*/
class EpsCell2d
{
Point<2> vertices[4];
/**
- * Data value from which the actual
- * colors will be computed by
- * the colorization function stated
- * in the <tt>EpsFlags</tt> class.
+ * Data value from which the actual colors will be computed by the
+ * colorization function stated in the <tt>EpsFlags</tt> class.
*/
float color_value;
/**
- * Depth into the picture, which
- * is defined as the distance from
- * an observer at an the origin in
- * direction of the line of sight.
+ * Depth into the picture, which is defined as the distance from
+ * an observer at an the origin in direction of the line of sight.
*/
float depth;
/**
- * Comparison operator for
- * sorting.
+ * Comparison operator for sorting.
*/
bool operator < (const EpsCell2d &) const;
};
/**
- * This is a helper function for
- * the <tt>write_gmv</tt>
- * function. There, the data in
- * the patches needs to be copied
- * around as output is one
- * variable globally at a time,
- * rather than all data on each
- * vertex at a time. This copying
- * around can be done detached
- * from the main thread, and is
- * thus moved into this separate
- * function.
+ * This is a helper function for the write_gmv() function. There,
+ * the data in the patches needs to be copied around as output is
+ * one variable globally at a time, rather than all data on each
+ * vertex at a time. This copying around can be done detached from
+ * the main thread, and is thus moved into this separate function.
*
- * Note that because of the
- * similarity of the formats,
- * this function is also used by
- * the Vtk and Tecplot output
- * functions.
+ * Note that because of the similarity of the formats, this function
+ * is also used by the Vtk and Tecplot output functions.
*/
template <int dim, int spacedim>
static void
*
* This class is thought as a base class to classes actually
* generating data for output. It has two abstract virtual functions,
- * <tt>get_patches</tt> and <tt>get_dataset_names</tt> which are to produce the data
- * which is actually needed. These are the only functions that need to
- * be overloaded by a derived class. In additional to that, it has a
+ * get_patches() and get_dataset_names() produce the data which is
+ * actually needed. These are the only functions that need to be
+ * overloaded by a derived class. In additional to that, it has a
* function for each output format supported by the underlying base
* class which gets the output data using these two virtual functions
* and passes them to the raw output functions.
* @endcode
*
* @note See DataOutBase::write_vtu or
- * DataOutInterface::write_pvtu_record for
- * writing solutions at each timestep.
+ * DataOutInterface::write_pvtu_record for writing solutions at each
+ * timestep.
*
* @note The second element of each pair, i.e., the file in which
* the graphical data for each time is stored, may itself be again
const std::vector<std::pair<double,std::string> > ×_and_names) const;
/**
- * This function is the exact
- * equivalent of the
- * write_pvtu_record() function
- * but for the VisIt
- * visualization program. See
- * there for the purpose of this
- * function.
+ * This function is the exact equivalent of the write_pvtu_record()
+ * function but for the VisIt visualization program. See there for
+ * the purpose of this function.
*
- * This function is documented
- * in the "Creating a master file
- * for parallel" section (section 5.7)
- * of the "Getting data into VisIt"
+ * This function is documented in the "Creating a master file for
+ * parallel" section (section 5.7) of the "Getting data into VisIt"
* report that can be found here:
* https://wci.llnl.gov/codes/visit/2.0.0/GettingDataIntoVisIt2.0.0.pdf
*/
const std::vector<std::string> &piece_names) const;
/**
- * Obtain data through get_patches()
- * and write it to <tt>out</tt>
- * in SVG format. See
- * DataOutBase::write_svg.
+ * Obtain data through get_patches() and write it to <tt>out</tt> in
+ * SVG format. See DataOutBase::write_svg.
*/
void write_svg(std::ostream &out) const;
/**
- * Obtain data through get_patches()
- * and write it to <tt>out</tt>
- * in deal.II intermediate
- * format. See
+ * Obtain data through get_patches() and write it to <tt>out</tt> in
+ * deal.II intermediate format. See
* DataOutBase::write_deal_II_intermediate.
*
- * Note that the intermediate
- * format is what its name
- * suggests: a direct
- * representation of internal
- * data. It isn't standardized
- * and will change whenever we
- * change our internal
- * representation. You can only
- * expect to process files
- * written in this format using
- * the same version of deal.II
- * that was used for writing.
+ * Note that the intermediate format is what its name suggests: a
+ * direct representation of internal data. It isn't standardized and
+ * will change whenever we change our internal representation. You
+ * can only expect to process files written in this format using the
+ * same version of deal.II that was used for writing.
*/
void write_deal_II_intermediate (std::ostream &out) const;
const OutputFormat output_format = default_format) const;
/**
- * Set the default format. The
- * value set here is used
- * anytime, output for format
- * <tt>default_format</tt> is
- * requested.
+ * Set the default format. The value set here is used anytime,
+ * output for format <tt>default_format</tt> is requested.
*/
void set_default_format (const OutputFormat default_format);
/**
- * Set the flags to be used for
- * output in OpenDX format.
+ * Set the flags to be used for output in OpenDX format.
*/
void set_flags (const DXFlags &dx_flags);
/**
- * Set the flags to be used for
- * output in UCD format.
+ * Set the flags to be used for output in UCD format.
*/
void set_flags (const UcdFlags &ucd_flags);
/**
- * Set the flags to be used for
- * output in GNUPLOT format.
+ * Set the flags to be used for output in GNUPLOT format.
*/
void set_flags (const GnuplotFlags &gnuplot_flags);
/**
- * Set the flags to be used for
- * output in POVRAY format.
+ * Set the flags to be used for output in POVRAY format.
*/
void set_flags (const PovrayFlags &povray_flags);
/**
- * Set the flags to be used for
- * output in EPS output.
+ * Set the flags to be used for output in EPS output.
*/
void set_flags (const EpsFlags &eps_flags);
/**
- * Set the flags to be used for
- * output in GMV format.
+ * Set the flags to be used for output in GMV format.
*/
void set_flags (const GmvFlags &gmv_flags);
/**
- * Set the flags to be used for
- * output in Tecplot format.
+ * Set the flags to be used for output in Tecplot format.
*/
void set_flags (const TecplotFlags &tecplot_flags);
/**
- * Set the flags to be used for
- * output in VTK format.
+ * Set the flags to be used for output in VTK format.
*/
void set_flags (const VtkFlags &vtk_flags);
/**
- * Set the flags to be used for
- * output in SVG format.
+ * Set the flags to be used for output in SVG format.
*/
void set_flags (const SvgFlags &svg_flags);
/**
- * Set the flags to be used for output in
- * deal.II intermediate format.
+ * Set the flags to be used for output in deal.II intermediate
+ * format.
*/
void set_flags (const Deal_II_IntermediateFlags &deal_II_intermediate_flags);
/**
- * A function that returns the same
- * string as the respective function in
- * the base class does; the only
- * exception being that if the parameter
- * is omitted, then the value for the
- * present default format is returned,
- * i.e. the correct suffix for the format
- * that was set through
- * set_default_format() or
- * parse_parameters() before calling this
- * function.
+ * A function that returns the same string as the respective
+ * function in the base class does; the only exception being that if
+ * the parameter is omitted, then the value for the present default
+ * format is returned, i.e. the correct suffix for the format that
+ * was set through set_default_format() or parse_parameters() before
+ * calling this function.
*/
std::string
default_suffix (const OutputFormat output_format = default_format) const;
/**
- * Declare parameters for all
- * output formats by declaring
- * subsections within the
- * parameter file for each output
- * format and call the respective
- * <tt>declare_parameters</tt>
- * functions of the flag classes
- * for each output format.
- *
- * Some of the declared
- * subsections may not contain
- * entries, if the respective
- * format does not export any
- * flags.
- *
- * Note that the top-level
- * parameters denoting the number
- * of subdivisions per patch and
- * the output format are not
- * declared, since they are only
- * passed to virtual functions
- * and are not stored inside
- * objects of this type. You have
- * to declare them yourself.
+ * Declare parameters for all output formats by declaring
+ * subsections within the parameter file for each output format and
+ * call the respective <tt>declare_parameters</tt> functions of the
+ * flag classes for each output format.
+ *
+ * Some of the declared subsections may not contain entries, if the
+ * respective format does not export any flags.
+ *
+ * Note that the top-level parameters denoting the number of
+ * subdivisions per patch and the output format are not declared,
+ * since they are only passed to virtual functions and are not
+ * stored inside objects of this type. You have to declare them
+ * yourself.
*/
static void declare_parameters (ParameterHandler &prm);
/**
- * Read the parameters declared
- * in <tt>declare_parameters</tt> and
- * set the flags for the output
- * formats accordingly.
+ * Read the parameters declared in declare_parameters() and
+ * set the flags for the output formats accordingly.
*
- * The flags thus obtained
- * overwrite all previous
- * contents of the flag objects
- * as default-constructed or set
- * by the set_flags() function.
+ * The flags thus obtained overwrite all previous contents of the
+ * flag objects as default-constructed or set by the set_flags()
+ * function.
*/
void parse_parameters (ParameterHandler &prm);
/**
- * Determine an estimate for
- * the memory consumption (in
- * bytes) of this
- * object. Since sometimes
- * the size of objects can
- * not be determined exactly
- * (for example: what is the
- * memory consumption of an
- * STL <tt>std::map</tt> type with a
- * certain number of
- * elements?), this is only
- * an estimate. however often
- * quite close to the true
- * value.
+ * Determine an estimate for the memory consumption (in bytes) of
+ * this object. Since sometimes the size of objects can not be
+ * determined exactly (for example: what is the memory consumption
+ * of an STL <tt>std::map</tt> type with a certain number of
+ * elements?), this is only an estimate. however often quite close
+ * to the true value.
*/
std::size_t memory_consumption () const;
protected:
/**
- * This is the abstract function
- * through which derived classes
- * propagate preprocessed data in
- * the form of Patch
- * structures (declared in the
- * base class DataOutBase) to
- * the actual output
- * function. You need to overload
- * this function to allow the
- * output functions to know what
- * they shall print.
+ * This is the abstract function through which derived classes
+ * propagate preprocessed data in the form of Patch structures
+ * (declared in the base class DataOutBase) to the actual output
+ * function. You need to overload this function to allow the output
+ * functions to know what they shall print.
*/
virtual
const std::vector<typename DataOutBase::Patch<dim,spacedim> > &
get_patches () const = 0;
/**
- * Abstract virtual function
- * through which the names of
- * data sets are obtained by the
- * output functions of the base
- * class.
+ * Abstract virtual function through which the names of data sets
+ * are obtained by the output functions of the base class.
*/
virtual
std::vector<std::string>
get_dataset_names () const = 0;
/**
- * This functions returns
- * information about how the
- * individual components of
- * output files that consist of
- * more than one data set are to
- * be interpreted.
- *
- * It returns a list of index
- * pairs and corresponding name
- * indicating which components of
- * the output are to be
- * considered vector-valued
- * rather than just a collection
- * of scalar data. The index
- * pairs are inclusive; for
- * example, if we have a Stokes
- * problem in 2d with components
- * (u,v,p), then the
- * corresponding vector data
- * range should be (0,1), and the
- * returned list would consist of
- * only a single element with a
- * tuple such as (0,1,"velocity").
- *
- * Since some of the derived
- * classes do not know about
- * vector data, this function has
- * a default implementation that
- * simply returns an empty
- * string, meaning that all data
- * is to be considered a
+ * This functions returns information about how the individual
+ * components of output files that consist of more than one data set
+ * are to be interpreted.
+ *
+ * It returns a list of index pairs and corresponding name
+ * indicating which components of the output are to be considered
+ * vector-valued rather than just a collection of scalar data. The
+ * index pairs are inclusive; for example, if we have a Stokes
+ * problem in 2d with components (u,v,p), then the corresponding
+ * vector data range should be (0,1), and the returned list would
+ * consist of only a single element with a tuple such as
+ * (0,1,"velocity").
+ *
+ * Since some of the derived classes do not know about vector data,
+ * this function has a default implementation that simply returns an
+ * empty string, meaning that all data is to be considered a
* collection of scalar fields.
*/
virtual
get_vector_data_ranges () const;
/**
- * The default number of
- * subdivisions for patches. This
- * is filled by parse_parameters()
- * and should be obeyed by
- * build_patches() in derived
- * classes.
+ * The default number of subdivisions for patches. This is filled by
+ * parse_parameters() and should be obeyed by build_patches() in
+ * derived classes.
*/
unsigned int default_subdivisions;
private:
/**
- * Standard output format. Use
- * this format, if output format
- * default_format is
- * requested. It can be changed
- * by the <tt>set_format</tt> function
- * or in a parameter file.
+ * Standard output format. Use this format, if output format
+ * default_format is requested. It can be changed by the
+ * <tt>set_format</tt> function or in a parameter file.
*/
OutputFormat default_fmt;
/**
- * Flags to be used upon output
- * of OpenDX data. Can be changed by
- * using the <tt>set_flags</tt>
- * function.
+ * Flags to be used upon output of OpenDX data. Can be changed by
+ * using the <tt>set_flags</tt> function.
*/
DXFlags dx_flags;
/**
- * Flags to be used upon output
- * of UCD data. Can be changed by
- * using the <tt>set_flags</tt>
- * function.
+ * Flags to be used upon output of UCD data. Can be changed by using
+ * the <tt>set_flags</tt> function.
*/
UcdFlags ucd_flags;
/**
- * Flags to be used upon output
- * of GNUPLOT data. Can be
- * changed by using the
- * <tt>set_flags</tt> function.
+ * Flags to be used upon output of GNUPLOT data. Can be changed by
+ * using the <tt>set_flags</tt> function.
*/
GnuplotFlags gnuplot_flags;
/**
- * Flags to be used upon output
- * of POVRAY data. Can be changed
- * by using the <tt>set_flags</tt>
- * function.
+ * Flags to be used upon output of POVRAY data. Can be changed by
+ * using the <tt>set_flags</tt> function.
*/
PovrayFlags povray_flags;
/**
- * Flags to be used upon output
- * of EPS data in one space
- * dimension. Can be changed by
- * using the <tt>set_flags</tt>
+ * Flags to be used upon output of EPS data in one space
+ * dimension. Can be changed by using the <tt>set_flags</tt>
* function.
*/
EpsFlags eps_flags;
/**
- * Flags to be used upon output
- * of gmv data in one space
- * dimension. Can be changed by
- * using the <tt>set_flags</tt>
+ * Flags to be used upon output of gmv data in one space
+ * dimension. Can be changed by using the <tt>set_flags</tt>
* function.
*/
GmvFlags gmv_flags;
/**
- * Flags to be used upon output
- * of Tecplot data in one space
- * dimension. Can be changed by
- * using the <tt>set_flags</tt>
+ * Flags to be used upon output of Tecplot data in one space
+ * dimension. Can be changed by using the <tt>set_flags</tt>
* function.
*/
TecplotFlags tecplot_flags;
/**
- * Flags to be used upon output
- * of vtk data in one space
- * dimension. Can be changed by
- * using the <tt>set_flags</tt>
+ * Flags to be used upon output of vtk data in one space
+ * dimension. Can be changed by using the <tt>set_flags</tt>
* function.
*/
VtkFlags vtk_flags;
/**
- * Flags to be used upon output
- * of svg data in one space
- * dimension. Can be changed by
- * using the <tt>set_flags</tt>
+ * Flags to be used upon output of svg data in one space
+ * dimension. Can be changed by using the <tt>set_flags</tt>
* function.
*/
SvgFlags svg_flags;
/**
- * Flags to be used upon output of
- * deal.II intermediate data in one space
- * dimension. Can be changed by using the
- * <tt>set_flags</tt> function.
+ * Flags to be used upon output of deal.II intermediate data in one
+ * space dimension. Can be changed by using the <tt>set_flags</tt>
+ * function.
*/
Deal_II_IntermediateFlags deal_II_intermediate_flags;
};
{
public:
/**
- * Read a sequence of patches as
- * written previously by
- * <tt>DataOutBase::write_deal_II_intermediate</tt>
- * and store them in the present
- * object. This overwrites any
- * previous content.
+ * Read a sequence of patches as written previously by
+ * <tt>DataOutBase::write_deal_II_intermediate</tt> and store them
+ * in the present object. This overwrites any previous content.
*/
void read (std::istream &in);
/**
- * This function can be used to
- * merge the patches read by the
- * other object into the patches
- * that this present object
- * stores. 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. Alternatively, it may
- * also be used for parallel
- * programs, where each process
- * only generates output for its
- * share of the cells, even if
- * all processes can see all
- * cells.
- *
- * For this to work, the input
- * files for the present object
- * and the given argument 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
+ * This function can be used to merge the patches read by the other
+ * object into the patches that this present object stores. 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. Alternatively, it may also be used for parallel
+ * programs, where each process only generates output for its share
+ * of the cells, even if all processes can see all cells.
+ *
+ * For this to work, the input files for the present object and the
+ * given argument 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 read() for this
- * object after merging in
- * patches, the previous state is
- * overwritten, and the merged-in
- * patches are lost.
+ * If you call read() for this object after merging in patches, the
+ * previous state is overwritten, and the merged-in patches are
+ * lost.
*
- * 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.
*
- * The use of this function is
- * demonstrated in step-19.
+ * The use of this function is demonstrated in step-19.
*/
void merge (const DataOutReader<dim,spacedim> &other);
protected:
/**
- * This is the function
- * through which this class
- * propagates preprocessed data in
- * the form of Patch
- * structures (declared in the
- * base class DataOutBase) to
- * the actual output
- * function.
+ * This is the function through which this class propagates
+ * preprocessed data in the form of Patch structures (declared in
+ * the base class DataOutBase) to the actual output function.
*
- * It returns the patches as read
- * the last time a stream was
- * given to the read() function.
+ * It returns the patches as read the last time a stream was given
+ * to the read() function.
*/
virtual const std::vector<typename dealii::DataOutBase::Patch<dim,spacedim> > &
get_patches () const;
/**
- * Abstract virtual function
- * through which the names of
- * data sets are obtained by the
- * output functions of the base
- * class.
+ * Abstract virtual function through which the names of data sets
+ * are obtained by the output functions of the base class.
*
- * Return the names of the
- * variables as read the last
- * time we read a file.
+ * Return the names of the variables as read the last time we read a
+ * file.
*/
virtual std::vector<std::string> get_dataset_names () const;
/**
- * This functions returns
- * information about how the
- * individual components of
- * output files that consist of
- * more than one data set are to
- * be interpreted.
- *
- * It returns a list of index
- * pairs and corresponding name
- * indicating which components of
- * the output are to be
- * considered vector-valued
- * rather than just a collection
- * of scalar data. The index
- * pairs are inclusive; for
- * example, if we have a Stokes
- * problem in 2d with components
- * (u,v,p), then the
- * corresponding vector data
- * range should be (0,1), and the
- * returned list would consist of
- * only a single element with a
- * tuple such as (0,1,"velocity").
- *
- * Since some of the derived
- * classes do not know about
- * vector data, this function has
- * a default implementation that
- * simply returns an empty
- * string, meaning that all data
- * is to be considered a
+ * This functions returns information about how the individual
+ * components of output files that consist of more than one data set
+ * are to be interpreted.
+ *
+ * It returns a list of index pairs and corresponding name
+ * indicating which components of the output are to be considered
+ * vector-valued rather than just a collection of scalar data. The
+ * index pairs are inclusive; for example, if we have a Stokes
+ * problem in 2d with components (u,v,p), then the corresponding
+ * vector data range should be (0,1), and the returned list would
+ * consist of only a single element with a tuple such as
+ * (0,1,"velocity").
+ *
+ * Since some of the derived classes do not know about vector data,
+ * this function has a default implementation that simply returns an
+ * empty string, meaning that all data is to be considered a
* collection of scalar fields.
*/
virtual
private:
/**
- * Arrays holding the set of
- * patches as well as the names
- * of output variables, all of
- * which we read from an input
- * stream.
+ * Arrays holding the set of patches as well as the names of output
+ * variables, all of which we read from an input stream.
*/
std::vector<typename dealii::DataOutBase::Patch<dim,spacedim> > patches;
std::vector<std::string> dataset_names;
/**
- * Information about whether
- * certain components of the
- * output field are to be
- * considered vectors.
+ * Information about whether certain components of the output field
+ * are to be considered vectors.
*/
std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >
vector_data_ranges;
/**
- * This pattern matches a list of comma-separated values each of which
+ * This pattern matches a list of values separated by commas (or another
+ * string), each of which
* have to match a pattern given to the constructor. With two additional
* parameters, the number of elements this list has to have can be
* specified. If none is specified, the list may have zero or more
* Constructor. Take the given parameter as the specification of valid
* elements of the list.
*
- * The two other arguments can be used to denote minimal and maximal
- * allowable lengths of the list.
+ * The three other arguments can be used to denote minimal and maximal
+ * allowable lengths of the list, and the string that is used as a
+ * separator between elements of the list.
*/
List (const PatternBase &base_pattern,
const unsigned int min_elements = 0,
- const unsigned int max_elements = max_int_value);
+ const unsigned int max_elements = max_int_value,
+ const std::string &separator = ",");
/**
* Destructor.
*/
const unsigned int max_elements;
+ /**
+ * Separator between elements of the list.
+ */
+ const std::string separator;
+
/**
* Initial part of description
*/
* pattern given to the constructor. For each entry of the map,
* parameters have to be entered in the form <code>key: value</code>. In
* other words, a map is described in the form
- * <code>key1: value1, key2: value2, key3: value3, ...</code>.
+ * <code>key1: value1, key2: value2, key3: value3, ...</code>. A constructor
+ * argument allows to choose a delimiter between pairs other than the comma.
*
* With two additional parameters, the number of elements this list has
* to have can be specified. If none is specified, the map may have zero
* Constructor. Take the given parameter as the specification of valid
* elements of the list.
*
- * The two other arguments can be used to denote minimal and maximal
- * allowable lengths of the list.
+ * The three other arguments can be used to denote minimal and maximal
+ * allowable lengths of the list as well as the separator used to delimit
+ * pairs of the map.
*/
Map (const PatternBase &key_pattern,
const PatternBase &value_pattern,
const unsigned int min_elements = 0,
- const unsigned int max_elements = max_int_value);
+ const unsigned int max_elements = max_int_value,
+ const std::string &separator = ",");
/**
* Destructor.
*/
const unsigned int max_elements;
+ /**
+ * Separator between elements of the list.
+ */
+ const std::string separator;
+
/**
* Initial part of description
*/
* set Geometry = [0,1]x[0,3]
* @endcode
* Input may be sorted into subsection trees in order to give the input a
- * logical structure.
+ * logical structure, and input files may include other files.
*
* The ParameterHandler class is discussed in detail in the @ref step_19
* "step-19" example program, and is used in more realistic situations in
* <tt>=</tt> sign.
*
*
+ * <h3>Including other input files</h3>
+ *
+ * An input file can include other include files using the syntax
+ * @code
+ * ...
+ * include some_other_file.prm
+ * ...
+ * @endcode
+ * The file so referenced is searched for relative to the current
+ * directory (not relative to the directory in which the including
+ * parameter file is located, since this is not known to all three
+ * versions of the read_input() function).
+ *
+ *
* <h3>Reading data from input sources</h3>
*
- * In order to read input you can use three possibilities: reading from
+ * In order to read input there are three possibilities: reading from
* an <tt>std::istream</tt> object, reading from a file of which the name
* is given and reading from a string in memory in which the lines are
* separated by <tt>@\n</tt> characters. These possibilities are used as
virtual ~ParameterHandler ();
/**
- * Read input from a stream until stream returns <tt>eof</tt> condition
- * or error.
+ * Read input from a stream until the stream returns the <tt>eof</tt> condition
+ * or error. The second argument can be used to denote the name of the file
+ * (if that's what the input stream represents) we are reading from; this
+ * is only used when creating output for error messages.
*
* Return whether the read was successful.
*/
- virtual bool read_input (std::istream &input);
+ virtual bool read_input (std::istream &input,
+ const std::string &filename = "input file");
/**
* Read input from a file the name of which is given. The PathSearch
* this class is asked to write out all declarations to a stream using
* the print_parameters() function.
*
- * The function generates an exception if the default value doesn't match
- * the given pattern. An entry can be declared more than once without
+ * The function generates an exception of type ExcValueDoesNotMatchPattern
+ * if the default value doesn't match the given pattern, using the C++
+ * throw mechanism. However, this exception is only generated <i>after</i>
+ * the entry has been created; if you have code where no sensible default
+ * value for a parameter is possible, you can then catch and ignore this
+ * exception.
+ *
+ * @note An entry can be declared more than once without
* generating an error, for example to override an earlier default value.
*/
void declare_entry (const std::string &entry,
std::string get_current_full_path (const std::string &name) const;
/**
- * Scan one line of input. <tt>lineno</tt> is the number of the line
+ * Scan one line of input. <tt>input_filename</tt> and <tt>lineno</tt>
+ * are the name of the input file and the current number of the line
* presently scanned (for the logs if there are messages). Return
* <tt>false</tt> if line contained stuff that could not be understood,
* the uppermost subsection was to be left by an <tt>END</tt> or
* caller's variable is not changed.
*/
bool scan_line (std::string line,
+ const std::string &input_filename,
const unsigned int lineno);
friend class MultipleParameterLoop;
template <class DH, bool lda>
+inline
TriaIterator<DoFAccessor<DH::dimension-1,DH,lda> >
DoFCellAccessor<DH,lda>::face (const unsigned int i) const
{
}
+
template<class DH, bool lda>
inline
void DoFCellAccessor<DH,lda>::get_mg_dof_indices (std::vector<types::global_dof_index> &dof_indices) const
DoFAccessor<dim, DH,lda>::get_mg_dof_indices (this->level (), dof_indices);
}
+
+
template<class DH, bool lda>
inline
void DoFCellAccessor<DH,lda>::set_mg_dof_indices (const std::vector<types::global_dof_index> &dof_indices)
}
+
template<class DH, bool lda>
inline
void DoFCellAccessor<DH,lda>::get_active_or_mg_dof_indices (std::vector<types::global_dof_index> &dof_indices) const
template <class DH, bool lda>
template <class InputVector, typename number>
+inline
void
DoFCellAccessor<DH,lda>::get_dof_values (const InputVector &values,
Vector<number> &local_values) const
template <class DH, bool lda>
template <class InputVector, typename ForwardIterator>
+inline
void
DoFCellAccessor<DH,lda>::get_dof_values (const InputVector &values,
ForwardIterator local_values_begin,
template <class DH, bool lda>
template <class InputVector, typename ForwardIterator>
+inline
void
DoFCellAccessor<DH,lda>::get_dof_values (const ConstraintMatrix &constraints,
const InputVector &values,
template <class DH, bool lda>
template <class OutputVector, typename number>
+inline
void
DoFCellAccessor<DH,lda>::set_dof_values (const Vector<number> &local_values,
OutputVector &values) const
std::size_t
memory_consumption () const;
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNoComponentSelected);
+
private:
/**
* The actual component mask.
* indices of each local block. If it is false, then the block sizes are
* returned.
*
- * @todo Which way does this vector map the numbers?
+ * The vector <tt>renumbering</tt> will be indexed by the standard
+ * numbering of local degrees of freedom, namely first first vertex,
+ * then second vertex, after vertices lines, quads, and hexes. For
+ * each index, the entry indicates the index which this degree of
+ * freedom receives in a numbering scheme, where the first block is
+ * numbered completely before the second.
*/
template<int dim, int spacedim>
void compute_block_renumbering (
*
* To use this class, make sure that the
* Boundary::@p get_normals_at_vertices function is implemented
- * for the users boundary object.
+ * for the user's boundary object.
*
* For more information about the <tt>spacedim</tt> template parameter
* check the documentation of FiniteElement or the one of
{
public:
/**
- * Constructor. Pass the fixed
- * degree @p 3 down to the base
- * class, as a cubic mapping
- * suffices to generate a
- * continuous mapping of the
- * boundary.
+ * Constructor. Pass the fixed degree @p 3 down to the base class, as a
+ * cubic mapping suffices to generate a continuous mapping of the boundary.
*/
MappingC1 ();
/**
- * Return a pointer to a copy of the
- * present object. The caller of this
- * copy then assumes ownership of it.
+ * Return a pointer to a copy of the present object. The caller of this copy
+ * then assumes ownership of it.
*/
virtual
Mapping<dim,spacedim> *clone () const;
protected:
/**
- * For <tt>dim=2,3</tt>. Append the
- * support points of all shape
- * functions located on bounding
- * lines to the vector
- * @p a. Points located on the
- * line but on vertices are not
- * included.
+ * For <tt>dim=2,3</tt>. Append the support points of all shape functions
+ * located on bounding lines to the vector @p a. Points located on the line
+ * but on vertices are not included.
*
- * Needed by the
- * <tt>compute_support_points_simple(laplace)</tt>
- * functions. For <tt>dim=1</tt> this
- * function is empty.
+ * Needed by the <tt>compute_support_points_simple(laplace)</tt>
+ * functions. For <tt>dim=1</tt> this function is empty.
*
- * This function chooses the
- * respective points not such
- * that they are interpolating
- * the boundary (as does the base
- * class), but rather such that
- * the resulting cubic mapping is
- * a continuous one.
+ * This function chooses the respective points not such that they are
+ * interpolating the boundary (as does the base class), but rather such that
+ * the resulting cubic mapping is a continuous one.
*/
virtual void
add_line_support_points (const typename Triangulation<dim>::cell_iterator &cell,
std::vector<Point<dim> > &a) const;
/**
- * For <tt>dim=3</tt>. Append the
- * support points of all shape
- * functions located on bounding
- * faces (quads in 3d) to the
- * vector @p a. Points located
- * on the line but on vertices
- * are not included.
+ * For <tt>dim=3</tt>. Append the support points of all shape functions
+ * located on bounding faces (quads in 3d) to the vector @p a. Points
+ * located on the line but on vertices are not included.
*
- * Needed by the
- * @p compute_support_points_laplace
- * function. For <tt>dim=1</tt> and 2
- * this function is empty.
+ * Needed by the @p compute_support_points_laplace function. For
+ * <tt>dim=1</tt> and 2 this function is empty.
*
- * This function chooses the
- * respective points not such
- * that they are interpolating
- * the boundary (as does the base
- * class), but rather such that
- * the resulting cubic mapping is
- * a continuous one.
+ * This function chooses the respective points not such that they are
+ * interpolating the boundary (as does the base class), but rather such that
+ * the resulting cubic mapping is a continuous one.
*/
virtual void
add_quad_support_points(const typename Triangulation<dim>::cell_iterator &cell,
/*@{*/
/**
- * Mapping class that uses Qp-mappings on boundary cells. The mapping
- * shape functions make use of tensor product polynomials with
- * equidistant (on the unit cell) support points.
+ * Mapping class that uses Qp-mappings on boundary cells. The mapping shape
+ * functions make use of tensor product polynomials with unit cell support
+ * points equal to the points of the Gauss-Lobatto quadrature formula. These
+ * points give a well-conditioned interpolation also for very high orders and
+ * are therefore preferred over equidistant support points.
*
* For more details about Qp-mappings, see the `mapping' report at
* <tt>deal.II/doc/reports/mapping_q/index.html</tt> in the `Reports'
* check the documentation of FiniteElement or the one of
* Triangulation.
*
+ * @note Since the boundary description is closely tied to the unit cell
+ * support points, new boundary descriptions need to explicitly use the
+ * Gauss-Lobatto points.
+ *
* @author Ralf Hartmann, 2000, 2001, 2005; Guido Kanschat 2000, 2001
*/
template <int dim, int spacedim=dim>
{
public:
/**
- * Constructor. @p p gives the
- * degree of mapping polynomials
- * on boundary cells.
+ * Constructor. @p p gives the degree of mapping polynomials on boundary
+ * cells.
*
- * The second argument determines
- * whether the higher order
- * mapping should also be used on
- * interior cells. If its value
- * is <code>false</code> (the
- * default), the a lower-order
- * mapping is used in the
- * interior. This is sufficient
- * for most cases where higher
- * order mappings are only used
- * to better approximate the
- * boundary. In that case, cells
- * bounded by straight lines are
- * acceptable in the
- * interior. However, there are
- * cases where one would also
- * like to use a higher order
- * mapping in the interior. The
- * MappingQEulerian class is one
- * such case.
+ * The second argument determines whether the higher order mapping should
+ * also be used on interior cells. If its value is <code>false</code> (the
+ * default), the a lower-order mapping is used in the interior. This is
+ * sufficient for most cases where higher order mappings are only used to
+ * better approximate the boundary. In that case, cells bounded by straight
+ * lines are acceptable in the interior. However, there are cases where one
+ * would also like to use a higher order mapping in the interior. The
+ * MappingQEulerian class is one such case.
*/
MappingQ (const unsigned int p,
const bool use_mapping_q_on_all_cells = false);
/**
- * Copy constructor. Performs a
- * deep copy, i.e. duplicates
- * what #tensor_pols points to
- * instead of simply copying the
- * #tensor_pols pointer as done
- * by a default copy constructor.
+ * Copy constructor. Performs a deep copy, i.e. duplicates what #tensor_pols
+ * points to instead of simply copying the #tensor_pols pointer as done by a
+ * default copy constructor.
*/
MappingQ (const MappingQ<dim,spacedim> &mapping);
virtual ~MappingQ ();
/**
- * Transforms the point @p p on
- * the unit cell to the point
- * @p p_real on the real cell
- * @p cell and returns @p p_real.
+ * Transforms the point @p p on the unit cell to the point @p p_real on the
+ * real cell @p cell and returns @p p_real.
*/
virtual Point<spacedim>
transform_unit_to_real_cell (
const Point<dim> &p) const;
/**
- * Transforms the point @p p on
- * the real cell to the point
- * @p p_unit on the unit cell
- * @p cell and returns @p p_unit.
+ * Transforms the point @p p on the real cell to the point @p p_unit on the
+ * unit cell @p cell and returns @p p_unit.
*
- * Uses Newton iteration and the
- * @p transform_unit_to_real_cell
- * function.
+ * Uses Newton iteration and the @p transform_unit_to_real_cell function.
*
- * In the codimension one case,
- * this function returns the
- * normal projection of the real
- * point @p p on the curve or
- * surface identified by the @p
- * cell.
+ * In the codimension one case, this function returns the normal projection
+ * of the real point @p p on the curve or surface identified by the @p cell.
*
- * @note Polynomial mappings from
- * the reference (unit) cell coordinates
- * to the coordinate system of a real
- * cell are not always invertible if
- * the point for which the inverse
- * mapping is to be computed lies
- * outside the cell's boundaries.
- * In such cases, the current function
- * may fail to compute a point on
- * the reference cell whose image
- * under the mapping equals the given
- * point @p p. If this is the case
- * then this function throws an
- * exception of type
- * Mapping::ExcTransformationFailed .
- * Whether the given point @p p lies
- * outside the cell can therefore be
- * determined by checking whether the
- * return reference coordinates lie
- * inside of outside the reference
- * cell (e.g., using
- * GeometryInfo::is_inside_unit_cell)
- * or whether the exception mentioned
- * above has been thrown.
+ * @note Polynomial mappings from the reference (unit) cell coordinates to
+ * the coordinate system of a real cell are not always invertible if the
+ * point for which the inverse mapping is to be computed lies outside the
+ * cell's boundaries. In such cases, the current function may fail to
+ * compute a point on the reference cell whose image under the mapping
+ * equals the given point @p p. If this is the case then this function
+ * throws an exception of type Mapping::ExcTransformationFailed . Whether
+ * the given point @p p lies outside the cell can therefore be determined by
+ * checking whether the return reference coordinates lie inside of outside
+ * the reference cell (e.g., using GeometryInfo::is_inside_unit_cell) or
+ * whether the exception mentioned above has been thrown.
*/
virtual Point<dim>
transform_real_to_unit_cell (
const MappingType type) const;
/**
- * Return the degree of the
- * mapping, i.e. the value which
- * was passed to the constructor.
+ * Return the degree of the mapping, i.e. the value which was passed to the
+ * constructor.
*/
unsigned int get_degree () const;
/**
- * Return a pointer to a copy of the
- * present object. The caller of this
- * copy then assumes ownership of it.
+ * Return a pointer to a copy of the present object. The caller of this copy
+ * then assumes ownership of it.
*/
virtual
Mapping<dim,spacedim> *clone () const;
/**
- * Storage for internal data of
- * Q_degree transformation.
+ * Storage for internal data of Q_degree transformation.
*/
class InternalData : public MappingQ1<dim,spacedim>::InternalData
{
/**
- * Return an estimate (in
- * bytes) or the memory
- * consumption of this
- * object.
+ * Return an estimate (in bytes) or the memory consumption of this object.
*/
virtual std::size_t memory_consumption () const;
/**
- * Unit normal vectors. Used
- * for the alternative
- * computation of the normal
- * vectors. See doc of the
- * @p alternative_normals_computation
- * flag.
+ * Unit normal vectors. Used for the alternative computation of the normal
+ * vectors. See doc of the @p alternative_normals_computation flag.
*
- * Filled (hardcoded) once in
- * @p get_face_data.
+ * Filled (hardcoded) once in @p get_face_data.
*/
std::vector<std::vector<Point<dim> > > unit_normals;
/**
- * Flag that is set by the
- * <tt>fill_fe_[[sub]face]_values</tt>
- * function.
+ * Flag that is set by the <tt>fill_fe_[[sub]face]_values</tt> function.
*
- * If this flag is @p true
- * we are on an interior cell
- * and the
- * @p mapping_q1_data is
- * used.
+ * If this flag is @p true we are on an interior cell and the @p
+ * mapping_q1_data is used.
*/
bool use_mapping_q1_on_current_cell;
/**
- * On interior cells
- * @p MappingQ1 is used.
+ * On interior cells @p MappingQ1 is used.
*/
typename MappingQ1<dim,spacedim>::InternalData mapping_q1_data;
};
protected:
/**
- * Implementation of the interface in
- * Mapping.
+ * Implementation of the interface in Mapping.
*/
virtual void
fill_fe_values (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
CellSimilarity::Similarity &cell_similarity) const ;
/**
- * Implementation of the interface in
- * Mapping.
+ * Implementation of the interface in Mapping.
*/
virtual void
fill_fe_face_values (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
typename std::vector<Point<spacedim> > &normal_vectors) const ;
/**
- * Implementation of the interface in
- * Mapping.
+ * Implementation of the interface in Mapping.
*/
virtual void
fill_fe_subface_values (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
typename std::vector<Point<spacedim> > &normal_vectors) const ;
/**
- * For <tt>dim=2,3</tt>. Append the
- * support points of all shape
- * functions located on bounding
- * lines to the vector
- * @p a. Points located on the
- * line but not on vertices are not
- * included.
+ * For <tt>dim=2,3</tt>. Append the support points of all shape functions
+ * located on bounding lines to the vector @p a. Points located on the line
+ * but not on vertices are not included.
*
- * Needed by the
- * @p compute_support_points_laplace
- * function . For <tt>dim=1</tt> this
- * function is empty.
+ * Needed by the @p compute_support_points_laplace function . For
+ * <tt>dim=1</tt> this function is empty.
*
- * This function is made virtual
- * in order to allow derived
- * classes to choose shape
- * function support points
- * differently than the present
- * class, which chooses the
- * points as interpolation points
- * on the boundary.
+ * This function is made virtual in order to allow derived classes to choose
+ * shape function support points differently than the present class, which
+ * chooses the points as interpolation points on the boundary.
*/
virtual void
add_line_support_points (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
std::vector<Point<spacedim> > &a) const;
/**
- * For <tt>dim=3</tt>. Append the
- * support points of all shape
- * functions located on bounding
- * faces (quads in 3d) to the
- * vector @p a. Points located
- * on the quad but not on vertices
- * are not included.
+ * For <tt>dim=3</tt>. Append the support points of all shape functions
+ * located on bounding faces (quads in 3d) to the vector @p a. Points
+ * located on the quad but not on vertices are not included.
*
- * Needed by the
- * @p compute_support_points_laplace
- * function. For <tt>dim=1</tt> and
- * <tt>dim=2</tt> this function is
- * empty.
+ * Needed by the @p compute_support_points_laplace function. For
+ * <tt>dim=1</tt> and <tt>dim=2</tt> this function is empty.
*
- * This function is made virtual
- * in order to allow derived
- * classes to choose shape
- * function support points
- * differently than the present
- * class, which chooses the
- * points as interpolation points
- * on the boundary.
+ * This function is made virtual in order to allow derived classes to choose
+ * shape function support points differently than the present class, which
+ * chooses the points as interpolation points on the boundary.
*/
virtual void
add_quad_support_points(const typename Triangulation<dim,spacedim>::cell_iterator &cell,
const Quadrature<dim-1>& quadrature) const;
/**
- * Compute shape values and/or
- * derivatives.
+ * Compute shape values and/or derivatives.
*/
virtual void
compute_shapes_virtual (const std::vector<Point<dim> > &unit_points,
typename MappingQ1<dim,spacedim>::InternalData &data) const;
/**
- * This function is needed by the
- * constructor of <tt>MappingQ<dim,spacedim></tt>
- * for <tt>dim=</tt> 2 and 3.
+ * This function is needed by the constructor of
+ * <tt>MappingQ<dim,spacedim></tt> for <tt>dim=</tt> 2 and 3.
*
- * For <tt>degree<4</tt> this function
- * sets the
- * @p laplace_on_quad_vector to
- * the hardcoded data. For
- * <tt>degree>=4</tt> and MappingQ<2>
- * this vector is computed.
+ * For <tt>degree<4</tt> this function sets the @p laplace_on_quad_vector to
+ * the hardcoded data. For <tt>degree>=4</tt> and MappingQ<2> this vector is
+ * computed.
*
- * For the definition of the
- * @p laplace_on_quad_vector
- * please refer to equation (8)
- * of the `mapping' report.
+ * For the definition of the @p laplace_on_quad_vector please refer to
+ * equation (8) of the `mapping' report.
*/
void
set_laplace_on_quad_vector(Table<2,double> &loqvs) const;
/**
- * This function is needed by the
- * constructor of <tt>MappingQ<3></tt>.
+ * This function is needed by the constructor of <tt>MappingQ<3></tt>.
*
- * For <tt>degree==2</tt> this function
- * sets the
- * @p laplace_on_hex_vector to
- * the hardcoded data. For
- * <tt>degree>2</tt> this vector is
- * computed.
+ * For <tt>degree==2</tt> this function sets the @p laplace_on_hex_vector to
+ * the hardcoded data. For <tt>degree>2</tt> this vector is computed.
*
- * For the definition of the
- * @p laplace_on_hex_vector
- * please refer to equation (8)
- * of the `mapping' report.
+ * For the definition of the @p laplace_on_hex_vector please refer to
+ * equation (8) of the `mapping' report.
*/
void set_laplace_on_hex_vector(Table<2,double> &lohvs) const;
/**
- * Computes the
- * <tt>laplace_on_quad(hex)_vector</tt>.
+ * Computes the <tt>laplace_on_quad(hex)_vector</tt>.
*
- * Called by the
- * <tt>set_laplace_on_quad(hex)_vector</tt>
- * functions if the data is not
- * yet hardcoded.
+ * Called by the <tt>set_laplace_on_quad(hex)_vector</tt> functions if the
+ * data is not yet hardcoded.
*
- * For the definition of the
- * <tt>laplace_on_quad(hex)_vector</tt>
- * please refer to equation (8)
- * of the `mapping' report.
+ * For the definition of the <tt>laplace_on_quad(hex)_vector</tt> please
+ * refer to equation (8) of the `mapping' report.
*/
void compute_laplace_vector(Table<2,double> &lvs) const;
/**
- * Takes a
- * <tt>laplace_on_hex(quad)_vector</tt>
- * and applies it to the vector
- * @p a to compute the inner
- * support points as a linear
- * combination of the exterior
- * points.
+ * Takes a <tt>laplace_on_hex(quad)_vector</tt> and applies it to the vector
+ * @p a to compute the inner support points as a linear combination of the
+ * exterior points.
*
- * The vector @p a initially
- * contains the locations of the
- * @p n_outer points, the
- * @p n_inner computed inner
- * points are appended.
+ * The vector @p a initially contains the locations of the @p n_outer
+ * points, the @p n_inner computed inner points are appended.
*
- * See equation (7) of the
- * `mapping' report.
+ * See equation (7) of the `mapping' report.
*/
void apply_laplace_vector(const Table<2,double> &lvs,
std::vector<Point<spacedim> > &a) const;
/**
- * Computes the support points of
- * the mapping.
+ * Computes the support points of the mapping.
*/
virtual void compute_mapping_support_points(
const typename Triangulation<dim,spacedim>::cell_iterator &cell,
std::vector<Point<spacedim> > &a) const;
/**
- * Computes all support points of
- * the mapping shape
- * functions. The inner support
- * points (ie. support points in
- * quads for 2d, in hexes for 3d)
- * are computed using the
- * solution of a Laplace equation
- * with the position of the outer
- * support points as boundary
- * values, in order to make the
- * transformation as smooth as
- * possible.
+ * Computes all support points of the mapping shape functions. The inner
+ * support points (ie. support points in quads for 2d, in hexes for 3d) are
+ * computed using the solution of a Laplace equation with the position of
+ * the outer support points as boundary values, in order to make the
+ * transformation as smooth as possible.
*/
void compute_support_points_laplace(
const typename Triangulation<dim,spacedim>::cell_iterator &cell,
std::vector<Point<spacedim> > &a) const;
/**
- * Needed by the
- * @p laplace_on_quad function
- * (for <tt>dim==2</tt>). Filled by the
- * constructor.
+ * Needed by the @p laplace_on_quad function (for <tt>dim==2</tt>). Filled
+ * by the constructor.
*
* Sizes:
- * laplace_on_quad_vector.size()=
- * number of inner
- * unit_support_points
- * laplace_on_quad_vector[i].size()=
- * number of outer
- * unit_support_points, i.e.
- * unit_support_points on the
- * boundary of the quad
+ * laplace_on_quad_vector.size()= number of inner unit_support_points
+ * laplace_on_quad_vector[i].size()= number of outer unit_support_points,
+ * i.e. unit_support_points on the boundary of the quad
*
- * For the definition of this
- * vector see equation (8) of the
- * `mapping' report.
+ * For the definition of this vector see equation (8) of the `mapping'
+ * report.
*/
Table<2,double> laplace_on_quad_vector;
/**
- * Needed by the
- * @p laplace_on_hex function
- * (for <tt>dim==3</tt>). Filled by the
- * constructor.
+ * Needed by the @p laplace_on_hex function (for <tt>dim==3</tt>). Filled by
+ * the constructor.
*
- * For the definition of this
- * vector see equation (8) of the
- * `mapping' report.
+ * For the definition of this vector see equation (8) of the `mapping'
+ * report.
*/
Table<2,double> laplace_on_hex_vector;
<< "laplace_vector not set for degree=" << arg1 << ".");
/**
- * Degree @p p of the
- * polynomials used as shape
- * functions for the Qp mapping
+ * Degree @p p of the polynomials used as shape functions for the Qp mapping
* of cells at the boundary.
*/
const unsigned int degree;
/**
- * Number of inner mapping shape
- * functions.
+ * Number of inner mapping shape functions.
*/
const unsigned int n_inner;
/**
- * Number of mapping shape
- * functions on the boundary.
+ * Number of mapping shape functions on the boundary.
*/
const unsigned int n_outer;
/**
- * Pointer to the
- * @p dim-dimensional tensor
- * product polynomials used as
- * shape functions for the Qp
- * mapping of cells at the
- * boundary.
+ * Pointer to the @p dim-dimensional tensor product polynomials used as
+ * shape functions for the Qp mapping of cells at the boundary.
*/
const TensorProductPolynomials<dim> *tensor_pols;
/**
- * Number of the Qp tensor
- * product shape functions.
+ * Number of the Qp tensor product shape functions.
*/
const unsigned int n_shape_functions;
/**
- * Mapping from lexicographic to
- * to the Qp shape function
- * numbering. Its size is
- * @p dofs_per_cell.
+ * Mapping from lexicographic to to the Qp shape function numbering. Its
+ * size is @p dofs_per_cell.
*/
const std::vector<unsigned int> renumber;
/**
- * If this flag is set @p true
- * then @p MappingQ is used on
- * all cells, not only on
- * boundary cells.
+ * If this flag is set @p true then @p MappingQ is used on all cells, not
+ * only on boundary cells.
*/
const bool use_mapping_q_on_all_cells;
/**
- * An FE_Q object which is only needed in
- * 3D, since it knows how to reorder shape
- * functions/DoFs on non-standard
- * faces. This is used to reorder support
- * points in the same way. We could make
- * this a pointer to prevent construction
- * in 1D and 2D, but since memory and time
- * requirements are not particularly high
- * this seems unnecessary at the moment.
+ * An FE_Q object which is only needed in 3D, since it knows how to reorder
+ * shape functions/DoFs on non-standard faces. This is used to reorder
+ * support points in the same way. We could make this a pointer to prevent
+ * construction in 1D and 2D, but since memory and time requirements are not
+ * particularly high this seems unnecessary at the moment.
*/
const FE_Q<dim> feq;
+
+ /**
+ * Declare other MappingQ classes friends.
+ */
+ template <int,int> friend class MappingQ;
};
/*@}*/
{
public:
/**
- * Constructor. The first argument is
- * the polynomical degree of the desired
- * Qp mapping. It then takes a
- * <tt>Vector<double> &</tt> to specify the
- * transformation of the domain
- * from the reference to
- * the current configuration.
- * The organization of the
- * elements in the @p Vector
- * must follow the concept how
- * deal.II stores solutions that
- * are associated to a
- * triangulation. This is
- * automatically the case if the
- * @p Vector represents the
- * solution of the previous step
- * of a nonlinear problem.
- * Alternatively, the @p Vector
- * can be initialized by
+ * Constructor. The first argument is the polynomical degree of the desired
+ * Qp mapping. It then takes a <tt>Vector<double> &</tt> to specify the
+ * transformation of the domain from the reference to the current
+ * configuration. The organization of the elements in the @p Vector must
+ * follow the concept how deal.II stores solutions that are associated to a
+ * triangulation. This is automatically the case if the @p Vector
+ * represents the solution of the previous step of a nonlinear problem.
+ * Alternatively, the @p Vector can be initialized by
* <tt>DoFAccessor::set_dof_values()</tt>.
*/
const DoFHandler<dim,spacedim> &euler_dof_handler);
/**
- * Return a pointer to a copy of the
- * present object. The caller of this
- * copy then assumes ownership of it.
+ * Return a pointer to a copy of the present object. The caller of this copy
+ * then assumes ownership of it.
*/
virtual
Mapping<dim,spacedim> *clone () const;
/**
- * Always returns @p false because
- * MappingQ1Eulerian does not in general
- * preserve vertex locations (unless the
- * translation vector happens to provide
- * for zero displacements at vertex
- * locations).
+ * Always returns @p false because MappingQ1Eulerian does not in general
+ * preserve vertex locations (unless the translation vector happens to
+ * provide for zero displacements at vertex locations).
*/
bool preserves_vertex_locations () const;
protected:
/**
- * Implementation of the interface in
- * MappingQ. Overrides the function in
- * the base class, since we cannot use
- * any cell similarity for this class.
+ * Implementation of the interface in MappingQ. Overrides the function in
+ * the base class, since we cannot use any cell similarity for this class.
*/
virtual void
fill_fe_values (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
CellSimilarity::Similarity &cell_similarity) const;
/**
- * Reference to the vector of
- * shifts.
+ * Reference to the vector of shifts.
*/
SmartPointer<const VECTOR, MappingQEulerian<dim,VECTOR,spacedim> > euler_vector;
/**
- * Pointer to the DoFHandler to
- * which the mapping vector is
- * associated.
+ * Pointer to the DoFHandler to which the mapping vector is associated.
*/
-
SmartPointer<const DoFHandler<dim,spacedim>,MappingQEulerian<dim,VECTOR,spacedim> > euler_dof_handler;
private:
/**
- * Special quadrature rule used
- * to define the support points
- * in the reference configuration.
+ * Special quadrature rule used to define the support points in the
+ * reference configuration.
*/
class SupportQuadrature : public Quadrature<dim>
{
public:
/**
- * Constructor, with an argument
- * defining the desired polynomial
- * degree.
+ * Constructor, with an argument defining the desired polynomial degree.
*/
SupportQuadrature (const unsigned int map_degree);
};
/**
- * A member variable holding the
- * quadrature points in the right
- * order.
+ * A member variable holding the quadrature points in the right order.
*/
const SupportQuadrature support_quadrature;
/**
- * FEValues object used to query the
- * the given finite element field
- * at the support points in the
- * reference configuration.
+ * FEValues object used to query the the given finite element field at the
+ * support points in the reference configuration.
*
- * The variable is marked as
- * mutable since we have to call
- * FEValues::reinit from
- * compute_mapping_support_points,
- * a function that is 'const'.
+ * The variable is marked as mutable since we have to call FEValues::reinit
+ * from compute_mapping_support_points, a function that is 'const'.
*/
mutable FEValues<dim,spacedim> fe_values;
/**
- * A variable to guard access to
- * the fe_values variable.
+ * A variable to guard access to the fe_values variable.
*/
mutable Threads::Mutex fe_values_mutex;
/**
- * Compute the positions of the
- * support points in the current
- * configuration
+ * Compute the positions of the support points in the current configuration
*/
virtual void compute_mapping_support_points(
const typename Triangulation<dim,spacedim>::cell_iterator &cell,
virtual
void
create_notification (const Triangulation<dim, spacedim> &tria);
- }; // DEAL_II_DEPRECATED;
+ };
/**
* A structure that is used as an
#include <deal.II/base/config.h>
#include <deal.II/base/subscriptor.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/thread_management.h>
#include <deal.II/base/point.h>
#include <deal.II/grid/tria.h>
public:
/**
- * Type keeping information about
- * the normals at the vertices of
- * a face of a cell. Thus, there
- * are
- * <tt>GeometryInfo<dim>::vertices_per_face</tt>
- * normal vectors, that define
- * the tangent spaces of the
- * boundary at the vertices. Note
- * that the vectors stored in
- * this object are not required
- * to be normalized, nor to
- * actually point outward, as one
- * often will only want to check
- * for orthogonality to define
- * the tangent plane; if a
- * function requires the normals
- * to be normalized, then it must
- * do so itself.
+ * Type keeping information about the normals at the vertices of a face of a
+ * cell. Thus, there are <tt>GeometryInfo<dim>::vertices_per_face</tt>
+ * normal vectors, that define the tangent spaces of the boundary at the
+ * vertices. Note that the vectors stored in this object are not required to
+ * be normalized, nor to actually point outward, as one often will only want
+ * to check for orthogonality to define the tangent plane; if a function
+ * requires the normals to be normalized, then it must do so itself.
*
- * For obvious reasons, this
- * type is not useful in 1d.
+ * For obvious reasons, this type is not useful in 1d.
*/
typedef Tensor<1,spacedim> FaceVertexNormals[GeometryInfo<dim>::vertices_per_face];
/**
- * Destructor. Does nothing here, but
- * needs to be declared to make it
+ * Destructor. Does nothing here, but needs to be declared to make it
* virtual.
*/
virtual ~Boundary ();
/**
- * Return the point which shall
- * become the new middle vertex
- * of the two children of a
- * regular line. In 2D, this line
- * is a line at the boundary,
- * while in 3d, it is bounding a
- * face at the boundary (the
- * lines therefore is also on the
- * boundary).
+ * Return the point which shall become the new middle vertex of the two
+ * children of a regular line. In 2D, this line is a line at the boundary,
+ * while in 3d, it is bounding a face at the boundary (the lines therefore
+ * is also on the boundary).
*/
virtual
Point<spacedim>
get_new_point_on_line (const typename Triangulation<dim,spacedim>::line_iterator &line) const = 0;
/**
- * Return the point which shall
- * become the common point of the
- * four children of a quad at the
- * boundary in three or more
- * spatial dimensions. This
- * function therefore is only
- * useful in at least three
- * dimensions and should not be
- * called for lower dimensions.
+ * Return the point which shall become the common point of the four children
+ * of a quad at the boundary in three or more spatial dimensions. This
+ * function therefore is only useful in at least three dimensions and should
+ * not be called for lower dimensions.
*
- * This function is called after
- * the four lines bounding the
- * given @p quad are refined, so
- * you may want to use the
- * information provided by
- * <tt>quad->line(i)->child(j)</tt>,
- * <tt>i=0...3</tt>, <tt>j=0,1</tt>.
+ * This function is called after the four lines bounding the given @p quad
+ * are refined, so you may want to use the information provided by
+ * <tt>quad->line(i)->child(j)</tt>, <tt>i=0...3</tt>, <tt>j=0,1</tt>.
*
- * Because in 2D, this function
- * is not needed, it is not made
- * pure virtual, to avoid the
- * need to overload it. The
- * default implementation throws
- * an error in any case, however.
+ * Because in 2D, this function is not needed, it is not made pure virtual,
+ * to avoid the need to overload it. The default implementation throws an
+ * error in any case, however.
*/
virtual
Point<spacedim>
get_new_point_on_quad (const typename Triangulation<dim,spacedim>::quad_iterator &quad) const;
/**
- * Depending on <tt>dim=2</tt> or
- * <tt>dim=3</tt> this function
- * calls the
- * get_new_point_on_line or the
- * get_new_point_on_quad
- * function. It throws an
- * exception for
- * <tt>dim=1</tt>. This wrapper
- * allows dimension independent
+ * Depending on <tt>dim=2</tt> or <tt>dim=3</tt> this function calls the
+ * get_new_point_on_line or the get_new_point_on_quad function. It throws an
+ * exception for <tt>dim=1</tt>. This wrapper allows dimension independent
* programming.
*/
Point<spacedim>
get_new_point_on_face (const typename Triangulation<dim,spacedim>::face_iterator &face) const;
/**
- * Return equally spaced
- * intermediate points on a line.
+ * Return intermediate points on a line spaced according to the interior
+ * support points of the 1D Gauss-Lobatto quadrature formula.
*
- * The number of points requested
- * is given by the size of the
- * vector @p points. It is the
- * task of the derived classes to
- * arrange the points in
+ * The number of points requested is given by the size of the vector @p
+ * points. It is the task of the derived classes to arrange the points in
* approximately equal distances.
*
- * This function is called by the
- * @p MappingQ class. This
- * happens on each face line of a
- * cells that has got at least
- * one boundary line.
+ * This function is called by the @p MappingQ class. This happens on each
+ * face line of a cells that has got at least one boundary line.
*
- * As this function is not needed
- * for @p MappingQ1, it is not
- * made pure virtual, to avoid
- * the need to overload it. The
- * default implementation throws
- * an error in any case, however.
+ * As this function is not needed for @p MappingQ1, it is not made pure
+ * virtual, to avoid the need to overload it. The default implementation
+ * throws an error in any case, however.
*/
virtual
void
std::vector<Point<spacedim> > &points) const;
/**
- * Return equally spaced
- * intermediate points on a
- * boundary quad.
+ * Return intermediate points on a line spaced according to the tensor
+ * product of the interior support points of the 1D Gauss-Lobatto quadrature
+ * formula.
*
- * The number of points requested
- * is given by the size of the
- * vector @p points. It is
- * required that this number is a
- * square of another integer,
- * i.e. <tt>n=points.size()=m*m</tt>. It
- * is the task of the derived
- * classes to arrange the points
- * such they split the quad into
- * <tt>(m+1)(m+1)</tt> approximately
- * equal-sized subquads.
+ * The number of points requested is given by the size of the vector @p
+ * points. It is required that this number is a square of another integer,
+ * i.e. <tt>n=points.size()=m*m</tt>. It is the task of the derived classes
+ * to arrange the points such they split the quad into <tt>(m+1)(m+1)</tt>
+ * approximately equal-sized subquads.
*
- * This function is called by the
- * <tt>MappingQ<3></tt> class. This
- * happens each face quad of
- * cells in 3d that has got at
- * least one boundary face quad.
+ * This function is called by the <tt>MappingQ<3></tt> class. This happens
+ * each face quad of cells in 3d that has got at least one boundary face
+ * quad.
*
- * As this function is not needed
- * for @p MappingQ1, it is not
- * made pure virtual, to avoid
- * the need to overload it. The
- * default implementation throws
- * an error in any case, however.
+ * As this function is not needed for @p MappingQ1, it is not made pure
+ * virtual, to avoid the need to overload it. The default implementation
+ * throws an error in any case, however.
*/
virtual
void
std::vector<Point<spacedim> > &points) const;
/**
- * Depending on <tt>dim=2</tt> or
- * <tt>dim=3</tt> this function
- * calls the
- * get_intermediate_points_on_line
- * or the
- * get_intermediate_points_on_quad
- * function. It throws an
- * exception for
- * <tt>dim=1</tt>. This wrapper
- * allows dimension independent
- * programming.
+ * Depending on <tt>dim=2</tt> or <tt>dim=3</tt> this function calls the
+ * get_intermediate_points_on_line or the get_intermediate_points_on_quad
+ * function. It throws an exception for <tt>dim=1</tt>. This wrapper allows
+ * dimension independent programming.
*/
void
get_intermediate_points_on_face (const typename Triangulation<dim,spacedim>::face_iterator &face,
std::vector<Point<spacedim> > &points) const;
/**
- * Return the normal vector to the surface
- * at the point p. If p is not in fact
- * on the surface, but only closeby,
- * try to return something reasonable,
- * for example the normal vector
- * at the surface point closest to p.
- * (The point p will in fact not normally
- * lie on the actual surface, but rather
- * be a quadrature point mapped by some
- * polynomial mapping; the mapped surface,
- * however, will not usually coincide with
- * the actual surface.)
+ * Return the normal vector to the surface at the point p. If p is not in
+ * fact on the surface, but only close-by, try to return something
+ * reasonable, for example the normal vector at the surface point closest to
+ * p. (The point p will in fact not normally lie on the actual surface, but
+ * rather be a quadrature point mapped by some polynomial mapping; the
+ * mapped surface, however, will not usually coincide with the actual
+ * surface.)
*
- * The face iterator gives an indication
- * which face this function is supposed
- * to compute the normal vector for.
- * This is useful if the boundary of
- * the domain is composed of different
- * nondifferential pieces (for example
- * when using the StraightBoundary class
- * to approximate a geometry that is
- * completely described by the coarse mesh,
- * with piecewise (bi-)linear components
- * between the vertices, but where the
- * boundary may have a kink at the vertices
- * itself).
+ * The face iterator gives an indication which face this function is
+ * supposed to compute the normal vector for. This is useful if the
+ * boundary of the domain is composed of different nondifferential pieces
+ * (for example when using the StraightBoundary class to approximate a
+ * geometry that is completely described by the coarse mesh, with piecewise
+ * (bi-)linear components between the vertices, but where the boundary may
+ * have a kink at the vertices itself).
*
- * @note Implementations of this function
- * should be able to assume that the point p
- * lies within or close to the face described by the
- * first argument. In turn, callers of this
- * function should ensure that this is
- * in fact the case.
+ * @note Implementations of this function should be able to assume that the
+ * point p lies within or close to the face described by the first
+ * argument. In turn, callers of this function should ensure that this is in
+ * fact the case.
*/
virtual
Tensor<1,spacedim>
const Point<spacedim> &p) const;
/**
- * Compute the normal vectors to
- * the boundary at each vertex of
- * the given face. It is not
- * required that the normal
- * vectors be normed
- * somehow. Neither is it
- * required that the normals
- * actually point outward.
+ * Compute the normal vectors to the boundary at each vertex of the given
+ * face. It is not required that the normal vectors be normed
+ * somehow. Neither is it required that the normals actually point outward.
*
- * This function is
- * needed to compute data for C1
- * mappings. The default
- * implementation is to throw an
- * error, so you need not
- * overload this function in case
- * you do not intend to use C1
- * mappings.
+ * This function is needed to compute data for C1 mappings. The default
+ * implementation is to throw an error, so you need not overload this
+ * function in case you do not intend to use C1 mappings.
*
- * Note that when computing
- * normal vectors at a vertex
- * where the boundary is not
- * differentiable, you have to
- * make sure that you compute the
- * one-sided limits, i.e. limit
- * with respect to points inside
- * the given face.
+ * Note that when computing normal vectors at a vertex where the boundary is
+ * not differentiable, you have to make sure that you compute the one-sided
+ * limits, i.e. limit with respect to points inside the given face.
*/
virtual
void
FaceVertexNormals &face_vertex_normals) const;
/**
- * Given a candidate point and a
- * line segment characterized by
- * the iterator, return a point
- * that lies on the surface
- * described by this object. This
- * function is used in some mesh
- * smoothing algorithms that try
- * to move around points in order
- * to improve the mesh quality
- * but need to ensure that points
- * that were on the boundary
- * remain on the boundary.
+ * Given a candidate point and a line segment characterized by the iterator,
+ * return a point that lies on the surface described by this object. This
+ * function is used in some mesh smoothing algorithms that try to move
+ * around points in order to improve the mesh quality but need to ensure
+ * that points that were on the boundary remain on the boundary.
*
- * If spacedim==1, then the line
- * represented by the line
- * iterator is the entire space
- * (i.e. it is a cell, not a part
- * of the boundary), and the
- * returned point equals the
- * given input point.
+ * If spacedim==1, then the line represented by the line iterator is the
+ * entire space (i.e. it is a cell, not a part of the boundary), and the
+ * returned point equals the given input point.
*
- * Derived classes do not need to
- * implement this function unless
- * mesh smoothing algorithms are
- * used with a particular
- * boundary object. The default
- * implementation of this
- * function throws an exception
- * of type ExcPureFunctionCalled.
+ * Derived classes do not need to implement this function unless mesh
+ * smoothing algorithms are used with a particular boundary object. The
+ * default implementation of this function throws an exception of type
+ * ExcPureFunctionCalled.
*/
virtual
Point<spacedim>
const Point<spacedim> &candidate) const;
/**
- * Same function as above but for
- * a point that is to be
- * projected onto the area
- * characterized by the given
- * quad.
+ * Same function as above but for a point that is to be projected onto the
+ * area characterized by the given quad.
*
- * If spacedim<=2, then the surface
- * represented by the quad
- * iterator is the entire space
- * (i.e. it is a cell, not a part
- * of the boundary), and the
- * returned point equals the
- * given input point.
+ * If spacedim<=2, then the surface represented by the quad iterator is the
+ * entire space (i.e. it is a cell, not a part of the boundary), and the
+ * returned point equals the given input point.
*/
virtual
Point<spacedim>
const Point<spacedim> &candidate) const;
/**
- * Same function as above but for
- * a point that is to be
- * projected onto the area
- * characterized by the given
- * quad.
+ * Same function as above but for a point that is to be projected onto the
+ * area characterized by the given quad.
*
- * If spacedim<=3, then the manifold
- * represented by the hex
- * iterator is the entire space
- * (i.e. it is a cell, not a part
- * of the boundary), and the
- * returned point equals the
- * given input point.
+ * If spacedim<=3, then the manifold represented by the hex iterator is the
+ * entire space (i.e. it is a cell, not a part of the boundary), and the
+ * returned point equals the given input point.
*/
virtual
Point<spacedim>
project_to_surface (const typename Triangulation<dim,spacedim>::hex_iterator &hex,
const Point<spacedim> &candidate) const;
+
+protected:
+ /**
+ * Returns the support points of the Gauss-Lobatto quadrature formula used
+ * for intermediate points.
+ *
+ * @note Since the boundary description is closely tied to the unit cell
+ * support points of MappingQ, new boundary descriptions need to explicitly
+ * use these Gauss-Lobatto points and not equidistant points.
+ */
+ const std::vector<Point<1> > &
+ get_line_support_points (const unsigned int n_intermediate_points) const;
+
+private:
+ /**
+ * Point generator for the intermediate points on a boundary.
+ */
+ mutable std::vector<std_cxx1x::shared_ptr<QGaussLobatto<1> > > points;
+
+ /**
+ * Mutex for protecting the points array.
+ */
+ mutable Threads::Mutex mutex;
};
{
public:
/**
- * Default constructor. Some
- * compilers require this for
- * some reasons.
+ * Default constructor. Some compilers require this for some reasons.
*/
StraightBoundary ();
/**
- * Let the new point be the
- * arithmetic mean of the two
- * vertices of the line.
+ * Let the new point be the arithmetic mean of the two vertices of the line.
*
- * Refer to the general
- * documentation of this class
- * and the documentation of the
- * base class for more
- * information.
+ * Refer to the general documentation of this class and the documentation of
+ * the base class for more information.
*/
virtual Point<spacedim>
get_new_point_on_line (const typename Triangulation<dim,spacedim>::line_iterator &line) const;
/**
- * Let the new point be the
- * arithmetic mean of the four
- * vertices of this quad and the
- * four midpoints of the lines,
- * which are already created at
- * the time of calling this
- * function.
+ * Let the new point be the arithmetic mean of the four vertices of this
+ * quad and the four midpoints of the lines, which are already created at
+ * the time of calling this function.
*
- * Refer to the general
- * documentation of this class
- * and the documentation of the
- * base class for more
- * information.
+ * Refer to the general documentation of this class and the documentation of
+ * the base class for more information.
*/
virtual
Point<spacedim>
get_new_point_on_quad (const typename Triangulation<dim,spacedim>::quad_iterator &quad) const;
/**
- * Gives <tt>n=points.size()</tt>
- * points that splits the
- * StraightBoundary line into
- * $n+1$ partitions of equal
- * lengths.
+ * Gives <tt>n=points.size()</tt> points that splits the StraightBoundary
+ * line into $n+1$ partitions of equal lengths.
*
- * Refer to the general
- * documentation of this class
- * and the documentation of the
- * base class.
+ * Refer to the general documentation of this class and the documentation of
+ * the base class.
*/
virtual
void
std::vector<Point<spacedim> > &points) const;
/**
- * Gives <tt>n=points.size()=m*m</tt>
- * points that splits the
- * StraightBoundary quad into
- * $(m+1)(m+1)$ subquads of equal
- * size.
+ * Gives <tt>n=points.size()=m*m</tt> points that splits the
+ * StraightBoundary quad into $(m+1)(m+1)$ subquads of equal size.
*
- * Refer to the general
- * documentation of this class
- * and the documentation of the
- * base class.
+ * Refer to the general documentation of this class and the documentation of
+ * the base class.
*/
virtual
void
std::vector<Point<spacedim> > &points) const;
/**
- * Implementation of the function
- * declared in the base class.
+ * Implementation of the function declared in the base class.
*
- * Refer to the general
- * documentation of this class
- * and the documentation of the
- * base class.
+ * Refer to the general documentation of this class and the documentation of
+ * the base class.
*/
virtual
Tensor<1,spacedim>
const Point<spacedim> &p) const;
/**
- * Compute the normals to the
- * boundary at the vertices of
- * the given face.
+ * Compute the normals to the boundary at the vertices of the given face.
*
- * Refer to the general
- * documentation of this class
- * and the documentation of the
- * base class.
+ * Refer to the general documentation of this class and the documentation of
+ * the base class.
*/
virtual
void
typename Boundary<dim,spacedim>::FaceVertexNormals &face_vertex_normals) const;
/**
- * Given a candidate point and a
- * line segment characterized by
- * the iterator, return a point
- * that lies on the surface
- * described by this object. This
- * function is used in some mesh
- * smoothing algorithms that try
- * to move around points in order
- * to improve the mesh quality
- * but need to ensure that points
- * that were on the boundary
- * remain on the boundary.
+ * Given a candidate point and a line segment characterized by the iterator,
+ * return a point that lies on the surface described by this object. This
+ * function is used in some mesh smoothing algorithms that try to move
+ * around points in order to improve the mesh quality but need to ensure
+ * that points that were on the boundary remain on the boundary.
*
- * The point returned is the
- * projection of the candidate
- * point onto the line through
- * the two vertices of the given
- * line iterator.
+ * The point returned is the projection of the candidate point onto the line
+ * through the two vertices of the given line iterator.
*
- * If spacedim==1, then the line
- * represented by the line
- * iterator is the entire space
- * (i.e. it is a cell, not a part
- * of the boundary), and the
- * returned point equals the
- * given input point.
+ * If spacedim==1, then the line represented by the line iterator is the
+ * entire space (i.e. it is a cell, not a part of the boundary), and the
+ * returned point equals the given input point.
*/
virtual
Point<spacedim>
const Point<spacedim> &candidate) const;
/**
- * Same function as above but for
- * a point that is to be
- * projected onto the area
- * characterized by the given
- * quad.
+ * Same function as above but for a point that is to be projected onto the
+ * area characterized by the given quad.
*
- * The point returned is the
- * projection of the candidate
- * point onto the bilinear
- * surface spanned by the four
- * vertices of the given quad
- * iterator.
+ * The point returned is the projection of the candidate point onto the
+ * bilinear surface spanned by the four vertices of the given quad iterator.
*
- * If spacedim<=2, then the surface
- * represented by the quad
- * iterator is the entire space
- * (i.e. it is a cell, not a part
- * of the boundary), and the
- * returned point equals the
- * given input point.
+ * If spacedim<=2, then the surface represented by the quad iterator is the
+ * entire space (i.e. it is a cell, not a part of the boundary), and the
+ * returned point equals the given input point.
*/
virtual
Point<spacedim>
const Point<spacedim> &candidate) const;
/**
- * Same function as above but for
- * a point that is to be
- * projected onto the area
- * characterized by the given
- * quad.
+ * Same function as above but for a point that is to be projected onto the
+ * area characterized by the given quad.
*
- * The point returned is the
- * projection of the candidate
- * point onto the trilinear
- * manifold spanned by the eight
- * vertices of the given hex
+ * The point returned is the projection of the candidate point onto the
+ * trilinear manifold spanned by the eight vertices of the given hex
* iterator.
*
- * If spacedim<=3, then the manifold
- * represented by the hex
- * iterator is the entire space
- * (i.e. it is a cell, not a part
- * of the boundary), and the
- * returned point equals the
- * given input point.
+ * If spacedim<=3, then the manifold represented by the hex iterator is the
+ * entire space (i.e. it is a cell, not a part of the boundary), and the
+ * returned point equals the given input point.
*/
virtual
Point<spacedim>
const dealii::hp::FECollection<dim,FEValues::space_dimension> &
get_fe_collection () const;
+ /**
+ * Get a reference to the collection of mapping objects used
+ * here.
+ */
+ const dealii::hp::MappingCollection<dim,FEValues::space_dimension> &
+ get_mapping_collection () const;
+
+ /**
+ * Get a reference to the collection of quadrature objects used
+ * here.
+ */
+ const dealii::hp::QCollection<q_dim> &
+ get_quadrature_collection () const;
+
+ /**
+ * Get the underlying update flags.
+ */
+ UpdateFlags get_update_flags() 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
{
return *fe_collection;
}
+
+
+
+ template <int dim, int q_dim, class FEValues>
+ inline
+ const dealii::hp::MappingCollection<dim,FEValues::space_dimension> &
+ FEValuesBase<dim,q_dim,FEValues>::get_mapping_collection () const
+ {
+ return *mapping_collection;
+ }
+
+
+
+ template <int dim, int q_dim, class FEValues>
+ inline
+ const dealii::hp::QCollection<q_dim> &
+ FEValuesBase<dim,q_dim,FEValues>::get_quadrature_collection () const
+ {
+ return q_collection;
+ }
+
+
+
+ template <int dim, int q_dim, class FEValues>
+ inline
+ dealii::UpdateFlags
+ FEValuesBase<dim,q_dim,FEValues>::get_update_flags () const
+ {
+ return update_flags;
+ }
}
}
}
}
+ template <int dim>
+ void ip_tangential_matrix (
+ FullMatrix<double> &M11,
+ FullMatrix<double> &M12,
+ FullMatrix<double> &M21,
+ FullMatrix<double> &M22,
+ const FEValuesBase<dim> &fe1,
+ const FEValuesBase<dim> &fe2,
+ double penalty,
+ double factor1 = 1.,
+ double factor2 = -1.)
+ {
+ const unsigned int n_dofs = fe1.dofs_per_cell;
+ AssertDimension(fe1.get_fe().n_components(), dim);
+ AssertDimension(fe2.get_fe().n_components(), dim);
+ AssertDimension(M11.n(), n_dofs);
+ AssertDimension(M11.m(), n_dofs);
+ AssertDimension(M12.n(), n_dofs);
+ AssertDimension(M12.m(), n_dofs);
+ AssertDimension(M21.n(), n_dofs);
+ AssertDimension(M21.m(), n_dofs);
+ AssertDimension(M22.n(), n_dofs);
+ AssertDimension(M22.m(), n_dofs);
+
+ const double nui = factor1;
+ const double nue = (factor2 < 0) ? factor1 : factor2;
+ const double nu = .5*(nui+nue);
+
+ for (unsigned int k=0; k<fe1.n_quadrature_points; ++k)
+ {
+ const double dx = fe1.JxW(k);
+ const Point<dim> &n = fe1.normal_vector(k);
+ for (unsigned int i=0; i<n_dofs; ++i)
+ {
+ for (unsigned int j=0; j<n_dofs; ++j)
+ {
+ double u1dotn = 0.;
+ double v1dotn = 0.;
+ double u2dotn = 0.;
+ double v2dotn = 0.;
+
+ for (unsigned int d=0; d<dim; ++d)
+ {
+ u1dotn += n(d)*fe1.shape_value_component(j,k,d);
+ v1dotn += n(d)*fe1.shape_value_component(i,k,d);
+ u2dotn += n(d)*fe2.shape_value_component(j,k,d);
+ v2dotn += n(d)*fe2.shape_value_component(i,k,d);
+ }
+
+ for (unsigned int d=0; d<fe1.get_fe().n_components(); ++d)
+ {
+
+ // multiply by
+ const double vi = fe1.shape_value_component(i,k,d)*(1-v1dotn);
+ const double dnvi = n * fe1.shape_grad_component(i,k,d)*(1-v1dotn);
+ const double ve = fe2.shape_value_component(i,k,d)*(1-v2dotn);
+ const double dnve = n * fe2.shape_grad_component(i,k,d)*(1-v2dotn);
+ const double ui = fe1.shape_value_component(j,k,d)*(1-u1dotn);
+ const double dnui = n * fe1.shape_grad_component(j,k,d)*(1-u1dotn);
+ const double ue = fe2.shape_value_component(j,k,d)*(1-u2dotn);
+ const double dnue = n * fe2.shape_grad_component(j,k,d)*(1-u2dotn);
+ M11(i,j) += dx*(-.5*nui*dnvi*ui-.5*nui*dnui*vi+nu*penalty*ui*vi);
+ M12(i,j) += dx*( .5*nui*dnvi*ue-.5*nue*dnue*vi-nu*penalty*vi*ue);
+ M21(i,j) += dx*(-.5*nue*dnve*ui+.5*nui*dnui*ve-nu*penalty*ui*ve);
+ M22(i,j) += dx*( .5*nue*dnve*ue+.5*nue*dnue*ve+nu*penalty*ue*ve);
+ }
+ }
+ }
+ }
+ }
+
/**
* Residual term for the symmetric interior penalty method.
*
*/
bool can_store_line (const size_type line_index) const;
+ /**
+ * Returns the index set describing locally relevant lines if any are
+ * present. Note that if no local lines were given, this represents an empty
+ * IndexSet, whereas otherwise it contains the global problem size and the
+ * local range.
+ */
+ const IndexSet & get_local_lines() const;
+
/**
* This function copies the content of @p
* constraints_in with DoFs that are
+inline
+const IndexSet &
+ConstraintMatrix::get_local_lines () const
+{
+ return local_lines;
+}
+
+
+
template <class VectorType>
inline
void ConstraintMatrix::distribute_local_to_global (
class SolverBase
{
public:
- /**
- * Declare type for container size.
- */
- typedef types::global_dof_index size_type;
-
/**
* Constructor. Takes the MPI communicator over which parallel
* computations are to happen.
solve (const PETScWrappers::MatrixBase &A,
std::vector<double> &eigenvalues,
std::vector<OutputVector> &eigenvectors,
- const size_type n_eigenpairs = 1);
+ const unsigned int n_eigenpairs = 1);
/**
* Same as above, but here a composite method for solving the
const PETScWrappers::MatrixBase &B,
std::vector<double> &eigenvalues,
std::vector<OutputVector> &eigenvectors,
- const size_type n_eigenpairs = 1);
+ const unsigned int n_eigenpairs = 1);
/**
* Same as above, but here a composite method for solving the
/**
* Solve the linear system for <code>n_eigenpairs</code>
* eigenstates. Parameter <code>n_converged</code> contains the
- * actual number of eigenstates that have . converged; this can
+ * actual number of eigenstates that have converged; this can
* be both fewer or more than n_eigenpairs, depending on the
* SLEPc eigensolver used.
*/
void
- solve (const unsigned int n_eigenpairs, unsigned int *n_converged);
+ solve (const unsigned int n_eigenpairs,
+ unsigned int *n_converged);
/**
* Access the real parts of solutions for a solved eigenvector
SolverBase::solve (const PETScWrappers::MatrixBase &A,
std::vector<double> &eigenvalues,
std::vector<OutputVector> &eigenvectors,
- const size_type n_eigenpairs)
+ const unsigned int n_eigenpairs)
{
// Panic if the number of eigenpairs wanted is out of bounds.
AssertThrow ((n_eigenpairs > 0) && (n_eigenpairs <= A.m ()),
set_matrices (A);
// and solve
- size_type n_converged = 0;
+ unsigned int n_converged = 0;
solve (n_eigenpairs, &n_converged);
if (n_converged > n_eigenpairs)
eigenvectors.resize (n_converged, eigenvectors.front());
eigenvalues.resize (n_converged);
- for (size_type index=0; index<n_converged; ++index)
+ for (unsigned int index=0; index<n_converged; ++index)
get_eigenpair (index, eigenvalues[index], eigenvectors[index]);
}
const PETScWrappers::MatrixBase &B,
std::vector<double> &eigenvalues,
std::vector<OutputVector> &eigenvectors,
- const size_type n_eigenpairs)
+ const unsigned int n_eigenpairs)
{
// Guard against incompatible matrix sizes:
AssertThrow (A.m() == B.m (), ExcDimensionMismatch(A.m(), B.m()));
set_matrices (A, B);
// and solve
- size_type n_converged = 0;
+ unsigned int n_converged = 0;
solve (n_eigenpairs, &n_converged);
if (n_converged>=n_eigenpairs)
eigenvectors.resize (n_converged, eigenvectors.front());
eigenvalues.resize (n_converged);
- for (size_type index=0; index<n_converged; ++index)
+ for (unsigned int index=0; index<n_converged; ++index)
get_eigenpair (index, eigenvalues[index], eigenvectors[index]);
}
std::vector<double> &imag_eigenvalues,
std::vector<OutputVector> &real_eigenvectors,
std::vector<OutputVector> &imag_eigenvectors,
- const size_type n_eigenpairs)
+ const unsigned int n_eigenpairs)
{
// Guard against incompatible matrix sizes:
AssertThrow (A.m() == B.m (), ExcDimensionMismatch(A.m(), B.m()));
set_matrices (A, B);
// and solve
- size_type n_converged = 0;
+ unsigned int n_converged = 0;
solve (n_eigenpairs, &n_converged);
if (n_converged>=n_eigenpairs)
real_eigenvalues.resize (n_converged);
imag_eigenvalues.resize (n_converged);
- for (size_type index=0; index<n_converged; ++index)
+ for (unsigned int index=0; index<n_converged; ++index)
get_eigenpair (index,
real_eigenvalues[index], imag_eigenvalues[index],
real_eigenvectors[index], imag_eigenvectors[index]);
IntegrationInfo();
/**
- * Copy constructor, creating a
- * clone to be used by
+ * Copy constructor, creating a clone to be used by
* WorksTream::run().
*/
IntegrationInfo(const IntegrationInfo<dim, spacedim> &other);
/**
- * Build all internal
- * structures, in particular
- * the FEValuesBase objects
- * and allocate space for
- * data vectors.
+ * Build all internal structures, in particular the FEValuesBase
+ * objects and allocate space for data vectors.
*
- * @param el is the finite
- * element of the DoFHandler.
+ * @param el is the finite element of the DoFHandler.
*
- * @param mapping is the Mapping
- * object used to map the
- * mesh cells.
+ * @param mapping is the Mapping object used to map the mesh
+ * cells.
*
- * @param quadrature is a
- * Quadrature formula used in
- * the constructor of the
- * FEVALUES objects.
+ * @param quadrature is a Quadrature formula used in the
+ * constructor of the FEVALUES objects.
*
- * @param flags are the
- * UpdateFlags used in
- * the constructor of the
+ * @param flags are the UpdateFlags used in the constructor of the
* FEVALUES objects.
*
- * @param local_block_info is
- * an optional parameter for
- * systems of PDE. If it is
- * provided with reasonable
- * data, then the degrees of
- * freedom on the cells will be
- * re-ordered to reflect the
- * block structure of the system.
+ * @param local_block_info is an optional parameter for systems of
+ * PDE. If it is provided with reasonable data, then the degrees
+ * of freedom on the cells will be re-ordered to reflect the block
+ * structure of the system.
*/
template <class FEVALUES>
void initialize(const FiniteElement<dim,spacedim> &el,
const BlockInfo *local_block_info = 0);
/**
- * Initialize the data
- * vector and cache the
- * selector.
+ * Initialize the data vector and cache the selector.
*/
void initialize_data(const std_cxx1x::shared_ptr<VectorDataBase<dim,spacedim> > &data);
bool multigrid;
/// Access to finite element
/**
- * This is the access
- * function being used, if
- * the constructor for a
- * single element was
- * used. It throws an
- * exception, if applied to a
- * vector of elements.
+ * This is the access function being used, if the constructor for
+ * a single element was used. It throws an exception, if applied
+ * to a vector of elements.
*/
const FEValuesBase<dim, spacedim> &fe_values () const;
/// Access to finite elements
/**
- * This access function must
- * be used if the constructor
- * for a group of elements
- * was used.
+ * This access function must be used if the constructor for a
+ * group of elements was used.
*
* @see DGBlockSplitApplication
*/
const FEValuesBase<dim, spacedim> &fe_values (const unsigned int i) const;
/**
- * The vector containing the
- * values of finite element
- * functions in the quadrature
- * points.
+ * The vector containing the values of finite element functions in
+ * the quadrature points.
*
- * There is one vector per
- * selected finite element
- * function, containing one
- * vector for each component,
- * containing vectors with
- * values for each quadrature
- * point.
+ * There is one vector per selected finite element function,
+ * containing one vector for each component, containing vectors
+ * with values for each quadrature point.
*/
std::vector<std::vector<std::vector<double> > > values;
/**
- * The vector containing the
- * derivatives of finite
- * element functions in the
- * quadrature points.
+ * The vector containing the derivatives of finite element
+ * functions in the quadrature points.
*
- * There is one vector per
- * selected finite element
- * function, containing one
- * vector for each component,
- * containing vectors with
- * values for each quadrature
- * point.
+ * There is one vector per selected finite element function,
+ * containing one vector for each component, containing vectors
+ * with values for each quadrature point.
*/
std::vector<std::vector<std::vector<Tensor<1,dim> > > > gradients;
/**
- * The vector containing the
- * second derivatives of finite
- * element functions in the
- * quadrature points.
+ * The vector containing the second derivatives of finite element
+ * functions in the quadrature points.
*
- * There is one vector per
- * selected finite element
- * function, containing one
- * vector for each component,
- * containing vectors with
- * values for each quadrature
- * point.
+ * There is one vector per selected finite element function,
+ * containing one vector for each component, containing vectors
+ * with values for each quadrature point.
*/
std::vector<std::vector<std::vector<Tensor<2,dim> > > > hessians;
/**
- * Reinitialize internal data
- * structures for use on a cell.
+ * Reinitialize internal data structures for use on a cell.
*/
template <typename number>
void reinit(const DoFInfo<dim, spacedim, number> &i);
/**
- * Use the finite element
- * functions in #global_data
- * and fill the vectors
- * #values, #gradients and
- * #hessians.
+ * Use the finite element functions in #global_data and fill the
+ * vectors #values, #gradients and #hessians.
*/
template<typename number>
void fill_local_data(const DoFInfo<dim, spacedim, number> &info, bool split_fevalues);
/**
- * The global data vector
- * used to compute function
- * values in quadrature
- * points.
+ * The global data vector used to compute function values in
+ * quadrature points.
*/
std_cxx1x::shared_ptr<VectorDataBase<dim, spacedim> > global_data;
private:
/**
- * Use the finite element
- * functions in #global_data
- * and fill the vectors
- * #values, #gradients and
- * #hessians with values
- * according to the
- * selector.
+ * Use the finite element functions in #global_data and fill the
+ * vectors #values, #gradients and #hessians with values according
+ * to the selector.
*/
template <typename TYPE>
void fill_local_data(
VectorSelector &selector,
bool split_fevalues) const;
/**
- * Cache the number of
- * components of the system element.
+ * Cache the number of components of the system element.
*/
unsigned int n_components;
};
IntegrationInfoBox ();
/**
- * Initialize the
- * IntegrationInfo objects
- * contained.
+ * Initialize the IntegrationInfo objects contained.
*
- * Before doing so, add update
- * flags necessary to produce
- * the data needed and also
- * set uninitialized quadrature
- * rules to Gauss formulas,
- * which integrate polynomial
- * bilinear forms exactly.
+ * Before doing so, add update flags necessary to produce the data
+ * needed and also set uninitialized quadrature rules to Gauss
+ * formulas, which integrate polynomial bilinear forms exactly.
*/
void initialize(const FiniteElement<dim, spacedim> &el,
const Mapping<dim, spacedim> &mapping,
const BlockInfo *block_info = 0);
/**
- * Initialize the
- * IntegrationInfo objects
- * contained.
+ * Initialize the IntegrationInfo objects contained.
*
- * Before doing so, add update
- * flags necessary to produce
- * the data needed and also
- * set uninitialized quadrature
- * rules to Gauss formulas,
- * which integrate polynomial
- * bilinear forms exactly.
+ * Before doing so, add update flags necessary to produce the data
+ * needed and also set uninitialized quadrature rules to Gauss
+ * formulas, which integrate polynomial bilinear forms exactly.
*/
template <typename VECTOR>
void initialize(const FiniteElement<dim, spacedim> &el,
const BlockInfo *block_info = 0);
/**
- * Initialize the
- * IntegrationInfo objects
- * contained.
+ * Initialize the IntegrationInfo objects contained.
*
- * Before doing so, add update
- * flags necessary to produce
- * the data needed and also
- * set uninitialized quadrature
- * rules to Gauss formulas,
- * which integrate polynomial
- * bilinear forms exactly.
+ * Before doing so, add update flags necessary to produce the data
+ * needed and also set uninitialized quadrature rules to Gauss
+ * formulas, which integrate polynomial bilinear forms exactly.
*/
template <typename VECTOR>
void initialize(const FiniteElement<dim, spacedim> &el,
/* @{ */
/**
- * Call this function before
- * initialize() in order to
- * guess the update flags
- * needed, based on the data
- * selected.
+ * Call this function before initialize() in order to guess the
+ * update flags needed, based on the data selected.
*
- * When computing face fluxes,
- * we normally can use the
- * geometry (integration
- * weights and normal vectors)
- * from the original cell and
- * thus can avoid updating
- * these values on the
- * neighboring cell. Set
- * <tt>neighbor_geometry</tt>
- * to true in order to
- * initialize these values as
- * well.
+ * When computing face fluxes, we normally can use the geometry
+ * (integration weights and normal vectors) from the original cell
+ * and thus can avoid updating these values on the neighboring
+ * cell. Set <tt>neighbor_geometry</tt> to true in order to
+ * initialize these values as well.
*/
void initialize_update_flags(bool neighbor_geometry = false);
/**
- * Add FEValues UpdateFlags for
- * integration on all objects
- * (cells, boundary faces and
- * all interior faces).
+ * Add FEValues UpdateFlags for integration on all objects (cells,
+ * boundary faces and all interior faces).
*/
void add_update_flags_all (const UpdateFlags flags);
/**
- * Add FEValues UpdateFlags for
- * integration on cells.
+ * Add FEValues UpdateFlags for integration on cells.
*/
void add_update_flags_cell(const UpdateFlags flags);
/**
- * Add FEValues UpdateFlags for
- * integration on boundary faces.
+ * Add FEValues UpdateFlags for integration on boundary faces.
*/
void add_update_flags_boundary(const UpdateFlags flags);
/**
- * Add FEValues UpdateFlags for
- * integration on interior faces.
+ * Add FEValues UpdateFlags for integration on interior faces.
*/
void add_update_flags_face(const UpdateFlags flags);
/**
- * Add additional update flags
- * to the ones already set in
- * this program. The four
- * boolean flags indicate
- * whether the additional flags
- * should be set for cell,
- * boundary, interelement face
- * for the cell itself
- * or neighbor cell, or
- * any combination thereof.
+ * Add additional update flags to the ones already set in this
+ * program. The four boolean flags indicate whether the additional
+ * flags should be set for cell, boundary, interelement face for
+ * the cell itself or neighbor cell, or any combination thereof.
*/
void add_update_flags(const UpdateFlags flags,
const bool cell = true,
const bool neighbor = true);
/**
- * Assign n-point Gauss
- * quadratures to each of the
- * quadrature rules. Here, a
- * size of zero points means
- * that no loop over these grid
- * entities should be
- * performed.
+ * Assign n-point Gauss quadratures to each of the quadrature
+ * rules. Here, a size of zero points means that no loop over
+ * these grid entities should be performed.
*
- * If the parameter
- * <tt>force</tt> is true, then
- * all quadrature sets are
- * filled with new quadrature
- * ruels. If it is false, then
+ * If the parameter <tt>force</tt> is true, then all quadrature
+ * sets are filled with new quadrature ruels. If it is false, then
* only empty rules are changed.
*/
void initialize_gauss_quadrature(unsigned int n_cell_points,
std::size_t memory_consumption () const;
/**
- * The set of update flags
- * for boundary cell integration.
+ * The set of update flags for boundary cell integration.
*
- * Defaults to
- * #update_JxW_values.
+ * Defaults to #update_JxW_values.
*/
UpdateFlags cell_flags;
/**
- * The set of update flags
- * for boundary face integration.
+ * The set of update flags for boundary face integration.
*
- * Defaults to
- * #update_JxW_values and
- * #update_normal_vectors.
+ * Defaults to #update_JxW_values and #update_normal_vectors.
*/
UpdateFlags boundary_flags;
/**
- * The set of update flags
- * for interior face integration.
+ * The set of update flags for interior face integration.
*
- * Defaults to
- * #update_JxW_values and
- * #update_normal_vectors.
+ * Defaults to #update_JxW_values and #update_normal_vectors.
*/
UpdateFlags face_flags;
/**
- * The set of update flags
- * for interior face integration.
+ * The set of update flags for interior face integration.
*
- * Defaults to
- * #update_default, since
- * quadrature weights are
- * taken from the other cell.
+ * Defaults to #update_default, since quadrature weights are taken
+ * from the other cell.
*/
UpdateFlags neighbor_flags;
/**
- * The quadrature rule used
- * on cells.
+ * The quadrature rule used on cells.
*/
Quadrature<dim> cell_quadrature;
/**
- * The quadrature rule used
- * on boundary faces.
+ * The quadrature rule used on boundary faces.
*/
Quadrature<dim-1> boundary_quadrature;
/**
- * The quadrature rule used
- * on interior faces.
+ * The quadrature rule used on interior faces.
*/
Quadrature<dim-1> face_quadrature;
/* @} */
/* @{ */
/**
- * Initialize the
- * VectorSelector objects
- * #cell_selector,
- * #boundary_selector and
- * #face_selector in order to
- * save computational
- * effort. If no selectors
- * are used, then values for
- * all named vectors in
- * DoFInfo::global_data will be
- * computed in all quadrature
- * points.
+ * Initialize the VectorSelector objects #cell_selector,
+ * #boundary_selector and #face_selector in order to save
+ * computational effort. If no selectors are used, then values for
+ * all named vectors in DoFInfo::global_data will be computed in
+ * all quadrature points.
*
- * This function will also
- * add UpdateFlags to the
- * flags stored in this class.
+ * This function will also add UpdateFlags to the flags stored in
+ * this class.
*/
/**
- * Select the vectors from
- * DoFInfo::global_data
- * that should be computed in
- * the quadrature points on cells.
+ * Select the vectors from DoFInfo::global_data that should be
+ * computed in the quadrature points on cells.
*/
MeshWorker::VectorSelector cell_selector;
/**
- * Select the vectors from
- * DoFInfo::global_data
- * that should be computed in
- * the quadrature points on
- * boundary faces.
+ * Select the vectors from DoFInfo::global_data that should be
+ * computed in the quadrature points on boundary faces.
*/
MeshWorker::VectorSelector boundary_selector;
/**
- * Select the vectors from
- * DoFInfo::global_data
- * that should be computed in
- * the quadrature points on
- * interior faces.
+ * Select the vectors from DoFInfo::global_data that should be
+ * computed in the quadrature points on interior faces.
*/
MeshWorker::VectorSelector face_selector;
*/
/* @{ */
/**
- * A callback function which is
- * called in the loop over all
- * cells, after the action on a
- * cell has been performed and
- * before the faces are dealt
- * with.
+ * A callback function which is called in the loop over all cells,
+ * after the action on a cell has been performed and before the
+ * faces are dealt with.
*
- * In order for this function
- * to have this effect,
- * at least either of the
- * arguments
- * <tt>boundary_worker</tt> or
- * <tt>face_worker</tt>
- * arguments of loop() should
- * be nonzero. Additionally,
- * <tt>cells_first</tt> should
- * be true. If
- * <tt>cells_first</tt> is
- * false, this function is
- * called before any action on
- * a cell is taken.
+ * In order for this function to have this effect, at least either
+ * of the arguments <tt>boundary_worker</tt> or
+ * <tt>face_worker</tt> arguments of loop() should be
+ * nonzero. Additionally, <tt>cells_first</tt> should be true. If
+ * <tt>cells_first</tt> is false, this function is called before
+ * any action on a cell is taken.
*
- * And empty function in this
- * class, but can be replaced
- * in other classes given to
- * loop() instead.
+ * And empty function in this class, but can be replaced in other
+ * classes given to loop() instead.
*
- * See loop() and cell_action()
- * for more details of how this
+ * See loop() and cell_action() for more details of how this
* function can be used.
*/
template <class DOFINFO>
void post_cell(const DoFInfoBox<dim, DOFINFO> &);
/**
- * A callback function which is
- * called in the loop over all
- * cells, after the action on
- * the faces of a cell has been
- * performed and before the
- * cell itself is dealt with
- * (assumes
+ * A callback function which is called in the loop over all cells,
+ * after the action on the faces of a cell has been performed and
+ * before the cell itself is dealt with (assumes
* <tt>cells_first</tt> is false).
*
- * In order for this function
- * to have a reasonable effect,
- * at least either of the
- * arguments
- * <tt>boundary_worker</tt> or
- * <tt>face_worker</tt>
- * arguments of loop() should
- * be nonzero. Additionally,
- * <tt>cells_first</tt> should
- * be false.
+ * In order for this function to have a reasonable effect, at
+ * least either of the arguments <tt>boundary_worker</tt> or
+ * <tt>face_worker</tt> arguments of loop() should be
+ * nonzero. Additionally, <tt>cells_first</tt> should be false.
*
- * And empty function in this
- * class, but can be replaced
- * in other classes given to
- * loop() instead.
+ * And empty function in this class, but can be replaced in other
+ * classes given to loop() instead.
*
- * See loop() and cell_action()
- * for more details of how this
+ * See loop() and cell_action() for more details of how this
* function can be used.
*/
template <class DOFINFO>
*/
CellInfo cell;
/**
- * The info object for a
- * boundary face.
+ * The info object for a boundary face.
*/
CellInfo boundary;
/**
- * The info object for a
- * regular interior face, seen
- * from the first cell.
+ * The info object for a regular interior face, seen from the
+ * first cell.
*/
CellInfo face;
/**
- * The info object for the
- * refined side of an interior
- * face seen from the first
- * cell.
+ * The info object for the refined side of an interior face seen
+ * from the first cell.
*/
CellInfo subface;
/**
- * The info object for an
- * interior face, seen from the
- * other cell.
+ * The info object for an interior face, seen from the other cell.
*/
CellInfo neighbor;
{
public:
/**
- * Constructor, initializing
- * the #threshold, which
- * limits how small numbers
- * may be to be entered into
- * the matrix.
+ * Constructor, initializing the #threshold, which limits how
+ * small numbers may be to be entered into the matrix.
*/
MGMatrixSimple(double threshold = 1.e-12);
/**
- * Store the result matrix
- * for later assembling.
+ * Store the result matrix for later assembling.
*/
void initialize(MGLevelObject<MATRIX> &m);
/**
- * Initialize the multilevel
- * constraints.
+ * Initialize the multilevel constraints.
*/
void initialize(const MGConstrainedDoFs &mg_constrained_dofs);
/**
- * @deprecated This function is of no effect. Only the block info
- * structure in DoFInfo is being used.
+ * @deprecated This function is of no effect. Only the block
+ * info structure in DoFInfo is being used.
*
* Store information on the local block structure. If the
* assembler is inititialized with this function,
*/
void initialize(MATRIX &m, VECTOR &rhs);
+ /**
+ * Initialize the constraints. After this function has been
+ * called with a valid ConstraintMatrix, the function
+ * ConstraintMatrix::distribute_local_to_global() will be used
+ * by assemble() to distribute the cell and face matrices into a
+ * global sparse matrix.
+ */
+ void initialize(const ConstraintMatrix &constraints);
+
/**
* Initialize the local data
* in the
for (unsigned int j=0; j<i1.size(); ++j)
for (unsigned int k=0; k<i2.size(); ++k)
if (std::fabs(M(k,j)) >= threshold)
- if (mg_constrained_dofs->at_refinement_edge(level, i1[j]) &&
- !mg_constrained_dofs->at_refinement_edge(level, i2[k]))
+ if (!mg_constrained_dofs->at_refinement_edge(level, i2[k]))
G.add(i1[j], i2[k], M(k,j));
}
}
for (unsigned int j=0; j<i1.size(); ++j)
for (unsigned int k=0; k<i2.size(); ++k)
if (std::fabs(M(j,k)) >= threshold)
- if (mg_constrained_dofs->at_refinement_edge(level, i1[j]) &&
- !mg_constrained_dofs->at_refinement_edge(level, i2[k]))
+ if (!mg_constrained_dofs->at_refinement_edge(level, i2[k]))
G.add(i1[j], i2[k], M(j,k));
}
}
{
AssertDimension(M.m(), i1.size());
AssertDimension(M.n(), i2.size());
-
- if (mg_constrained_dofs == 0)
- {
- for (unsigned int j=0; j<i1.size(); ++j)
- for (unsigned int k=0; k<i2.size(); ++k)
- if (std::fabs(M(j,k)) >= threshold)
- G.add(i1[j], i2[k], M(j,k));
- }
- else
- {
- for (unsigned int j=0; j<i1.size(); ++j)
- for (unsigned int k=0; k<i2.size(); ++k)
- if (std::fabs(M(j,k)) >= threshold)
- // Enter values into matrix only if j corresponds to a
- // degree of freedom on the refinemenent edge, k does
- // not, and both are not on the boundary. This is part
- // the difference between the complete matrix with no
- // boundary condition at the refinement edge and and
- // the matrix assembled above by assemble().
-
- // Thus the logic is: enter the row if it is
- // constrained by hanging node constraints (actually,
- // the whole refinement edge), but not if it is
- // constrained by a boundary constraint.
- if (mg_constrained_dofs->at_refinement_edge(level, i1[j]) &&
- !mg_constrained_dofs->at_refinement_edge(level, i2[k]))
- {
- if (mg_constrained_dofs->set_boundary_values())
- {
- if ((!mg_constrained_dofs->at_refinement_edge_boundary(level, i1[j]) &&
- !mg_constrained_dofs->at_refinement_edge_boundary(level, i2[k]))
- ||
- (mg_constrained_dofs->at_refinement_edge_boundary(level, i1[j]) &&
- mg_constrained_dofs->at_refinement_edge_boundary(level, i2[k]) &&
- i1[j] == i2[k]))
- G.add(i1[j], i2[k], M(j,k));
- }
- else
- G.add(i1[j], i2[k], M(j,k));
- }
- }
+ Assert(mg_constrained_dofs != 0, ExcInternalError());
+
+ for (unsigned int j=0; j<i1.size(); ++j)
+ for (unsigned int k=0; k<i2.size(); ++k)
+ if (std::fabs(M(j,k)) >= threshold)
+ // Enter values into matrix only if j corresponds to a
+ // degree of freedom on the refinemenent edge, k does
+ // not, and both are not on the boundary. This is part
+ // the difference between the complete matrix with no
+ // boundary condition at the refinement edge and and
+ // the matrix assembled above by assemble().
+
+ // Thus the logic is: enter the row if it is
+ // constrained by hanging node constraints (actually,
+ // the whole refinement edge), but not if it is
+ // constrained by a boundary constraint.
+ if (mg_constrained_dofs->at_refinement_edge(level, i1[j]) &&
+ !mg_constrained_dofs->at_refinement_edge(level, i2[k]))
+ {
+ if (mg_constrained_dofs->set_boundary_values())
+ {
+ if ((!mg_constrained_dofs->at_refinement_edge_boundary(level, i1[j]) &&
+ !mg_constrained_dofs->at_refinement_edge_boundary(level, i2[k]))
+ ||
+ (mg_constrained_dofs->at_refinement_edge_boundary(level, i1[j]) &&
+ mg_constrained_dofs->at_refinement_edge_boundary(level, i2[k]) &&
+ i1[j] == i2[k]))
+ G.add(i1[j], i2[k], M(j,k));
+ }
+ else
+ G.add(i1[j], i2[k], M(j,k));
+ }
}
-
+
+
template <class MATRIX>
inline void
MGMatrixSimple<MATRIX>::assemble_out(
{
AssertDimension(M.n(), i1.size());
AssertDimension(M.m(), i2.size());
-
- if (mg_constrained_dofs == 0)
- {
- for (unsigned int j=0; j<i1.size(); ++j)
- for (unsigned int k=0; k<i2.size(); ++k)
- if (std::fabs(M(k,j)) >= threshold)
- G.add(i1[j], i2[k], M(k,j));
- }
- else
- {
- for (unsigned int j=0; j<i1.size(); ++j)
- for (unsigned int k=0; k<i2.size(); ++k)
- if (std::fabs(M(k,j)) >= threshold)
- if (mg_constrained_dofs->at_refinement_edge(level, i1[j]) &&
- !mg_constrained_dofs->at_refinement_edge(level, i2[k]))
- {
- if (mg_constrained_dofs->set_boundary_values())
- {
- if ((!mg_constrained_dofs->at_refinement_edge_boundary(level, i1[j]) &&
- !mg_constrained_dofs->at_refinement_edge_boundary(level, i2[k]))
- ||
- (mg_constrained_dofs->at_refinement_edge_boundary(level, i1[j]) &&
- mg_constrained_dofs->at_refinement_edge_boundary(level, i2[k]) &&
- i1[j] == i2[k]))
- G.add(i1[j], i2[k], M(k,j));
- }
- else
- G.add(i1[j], i2[k], M(k,j));
- }
- }
+ Assert(mg_constrained_dofs != 0, ExcInternalError());
+
+ for (unsigned int j=0; j<i1.size(); ++j)
+ for (unsigned int k=0; k<i2.size(); ++k)
+ if (std::fabs(M(k,j)) >= threshold)
+ if (mg_constrained_dofs->at_refinement_edge(level, i1[j]) &&
+ !mg_constrained_dofs->at_refinement_edge(level, i2[k]))
+ {
+ if (mg_constrained_dofs->set_boundary_values())
+ {
+ if ((!mg_constrained_dofs->at_refinement_edge_boundary(level, i1[j]) &&
+ !mg_constrained_dofs->at_refinement_edge_boundary(level, i2[k]))
+ ||
+ (mg_constrained_dofs->at_refinement_edge_boundary(level, i1[j]) &&
+ mg_constrained_dofs->at_refinement_edge_boundary(level, i2[k]) &&
+ i1[j] == i2[k]))
+ G.add(i1[j], i2[k], M(k,j));
+ }
+ else
+ G.add(i1[j], i2[k], M(k,j));
+ }
}
-
+
template <class MATRIX>
template <class DOFINFO>
ResidualSimple<VECTOR>::initialize(data);
}
+ template <class MATRIX, class VECTOR>
+ inline void
+ SystemSimple<MATRIX,VECTOR>::initialize(const ConstraintMatrix &c)
+ {
+ MatrixSimple<MATRIX>::initialize(c);
+ ResidualSimple<VECTOR>::initialize(c);
+ }
+
template <class MATRIX, class VECTOR>
template <class DOFINFO>
inline void
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: mg_matrix.h 30036 2013-07-18 16:55:32Z maier $
+//
+// 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.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__mg_sparse_matrix_collection_h
+#define __deal2__mg_sparse_matrix_collection_h
+
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/pointer_matrix.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/compressed_sparsity_pattern.h>
+#include <deal.II/multigrid/mg_base.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/base/mg_level_object.h>
+#include <deal.II/base/std_cxx1x/shared_ptr.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+namespace mg
+{
+/**
+ * Handler and storage for all five SparseMatrix object involved in
+ * using multigrid with local refinement.
+ *
+ * @author Baerbel Janssen, Guido Kanschat
+ * @date 2013
+ */
+ template <typename number>
+ class SparseMatrixCollection : public Subscriptor
+ {
+ public:
+ void resize(const unsigned int minlevel, const unsigned int maxlevel);
+
+ template <class DH>
+ void reinit(const DH& dof_handler);
+
+ void set_zero();
+
+ MGLevelObject<SparsityPattern> sparsity;
+ MGLevelObject<SparsityPattern> sparsity_edge;
+
+ MGLevelObject<SparseMatrix<number> > matrix;
+ MGLevelObject<SparseMatrix<number> > matrix_down;
+ MGLevelObject<SparseMatrix<number> > matrix_up;
+ MGLevelObject<SparseMatrix<number> > matrix_in;
+ MGLevelObject<SparseMatrix<number> > matrix_out;
+ };
+
+
+ template <typename number>
+ void
+ SparseMatrixCollection<number>::resize(const unsigned int minlevel, const unsigned int maxlevel)
+ {
+ matrix.resize(minlevel, maxlevel);
+ matrix.clear();
+ matrix_up.resize(minlevel+1, maxlevel);
+ matrix_up.clear();
+ matrix_down.resize(minlevel+1, maxlevel);
+ matrix_down.clear();
+ matrix_in.resize(minlevel, maxlevel);
+ matrix_in.clear();
+ matrix_out.resize(minlevel, maxlevel);
+ matrix_out.clear();
+ sparsity.resize(minlevel, maxlevel);
+ sparsity_edge.resize(minlevel, maxlevel);
+ }
+
+
+ template <typename number>
+ template <class DH>
+ void
+ SparseMatrixCollection<number>::reinit(const DH& dof_handler)
+ {
+ AssertIndexRange(sparsity.max_level(), dof_handler.get_tria().n_levels());
+
+ for (unsigned int level=sparsity.min_level();
+ level<=sparsity.max_level();++level)
+ {
+ CompressedSparsityPattern c_sparsity(dof_handler.n_dofs(level));
+ MGTools::make_flux_sparsity_pattern(dof_handler, c_sparsity, level);
+ sparsity[level].copy_from(c_sparsity);
+ matrix[level].reinit(sparsity[level]);
+ matrix_in[level].reinit(sparsity[level]);
+ matrix_out[level].reinit(sparsity[level]);
+ if (level>0)
+ {
+ CompressedSparsityPattern ci_sparsity;
+ ci_sparsity.reinit(dof_handler.n_dofs(level-1), dof_handler.n_dofs(level));
+ MGTools::make_flux_sparsity_pattern_edge(dof_handler, ci_sparsity, level);
+ sparsity_edge[level].copy_from(ci_sparsity);
+ matrix_up[level].reinit(sparsity_edge[level]);
+ matrix_down[level].reinit(sparsity_edge[level]);
+ }
+ }
+ }
+
+ template <typename number>
+ void
+ SparseMatrixCollection<number>::set_zero()
+ {
+ matrix = 0.;
+ matrix_in = 0.;
+ matrix_out = 0.;
+ matrix_up = 0.;
+ matrix_down = 0.;
+ }
+
+}
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
#include <deal.II/base/config.h>
-#include <deal.II/base/smartpointer.h>
-#include <deal.II/base/data_out_base.h>
-#include <deal.II/dofs/dof_handler.h>
-#include <deal.II/grid/tria.h>
-#include <deal.II/fe/mapping.h>
-#include <deal.II/hp/q_collection.h>
-#include <deal.II/hp/fe_collection.h>
-#include <deal.II/hp/mapping_collection.h>
-#include <deal.II/hp/fe_values.h>
-#include <deal.II/numerics/data_postprocessor.h>
-#include <deal.II/numerics/data_component_interpretation.h>
+#include <deal.II/numerics/data_out_dof_data.h>
#include <deal.II/base/std_cxx1x/shared_ptr.h>
{
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.
- *
- * @author Wolfgang Bangerth, 2004
- */
- template <class DH>
- class DataEntryBase
- {
- 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.
- */
- DataEntryBase (const DH *dofs,
- const std::vector<std::string> &names,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &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.
- */
- DataEntryBase (const DH *dofs,
- const DataPostprocessor<DH::space_dimension> *data_postprocessor);
-
- /**
- * Destructor made virtual.
- */
- virtual ~DataEntryBase ();
-
- /**
- * Assuming that the stored vector is a cell vector, extract the given
- * element from it.
- */
- virtual
- double
- 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.
- */
- virtual
- void
- get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<double> &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.
- */
- virtual
- void
- get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<dealii::Vector<double> > &patch_values_system) const = 0;
-
- /**
- * Given a FEValuesBase object, extract the gradients on the present
- * cell from the vector we actually store.
- */
- virtual
- void
- get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<Tensor<1,DH::space_dimension> > &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.
- */
- virtual
- void
- get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<std::vector<Tensor<1,DH::space_dimension> > > &patch_gradients_system) const = 0;
-
- /**
- * Given a FEValuesBase object, extract the second derivatives on the
- * present cell from the vector we actually store.
- */
- virtual
- void
- get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<Tensor<2,DH::space_dimension> > &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.
- */
- virtual
- void
- get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<std::vector< Tensor<2,DH::space_dimension> > > &patch_hessians_system) const = 0;
-
- /**
- * Clear all references to the vectors.
- */
- virtual void clear () = 0;
-
- /**
- * Determine an estimate for the memory consumption (in bytes) of this
- * object.
- */
- virtual std::size_t memory_consumption () const = 0;
-
- /**
- * Pointer to the DoFHandler object that the vector is based on.
- */
- SmartPointer<const DH> dof_handler;
-
- /**
- * Names of the components of this data vector.
- */
- const std::vector<std::string> 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.
- */
- const std::vector<DataComponentInterpretation::DataComponentInterpretation>
- data_component_interpretation;
-
- /**
- * Pointer to a DataPostprocessing object which shall be applied to this
- * data vector.
- */
- SmartPointer<const dealii::DataPostprocessor<DH::space_dimension> > 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 <tt>names.size()</tt>.
- */
- 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.
- *
- * The <code>cell_to_patch_index_map</code> is an array that stores for
- * index <tt>[i][j]</tt> 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.
- */
- template <int dim, int spacedim>
- struct ParallelDataBase
- {
- ParallelDataBase (const unsigned int n_datasets,
- const unsigned int n_subdivisions,
- const std::vector<unsigned int> &n_postprocessor_outputs,
- const Mapping<dim,spacedim> &mapping,
- const std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<dim,spacedim> > > &finite_elements,
- const UpdateFlags update_flags,
- const bool use_face_values);
-
- ParallelDataBase (const ParallelDataBase &data);
-
- template <typename DH>
- void reinit_all_fe_values(std::vector<std_cxx1x::shared_ptr<DataEntryBase<DH> > > &dof_data,
- const typename dealii::Triangulation<dim,spacedim>::cell_iterator &cell,
- const unsigned int face = numbers::invalid_unsigned_int);
-
- const FEValuesBase<dim,spacedim> &
- get_present_fe_values(const unsigned int dataset) const;
-
- void resize_system_vectors(const unsigned int n_components);
-
- const unsigned int n_datasets;
- const unsigned int n_subdivisions;
-
- std::vector<double> patch_values;
- std::vector<dealii::Vector<double> > patch_values_system;
- std::vector<Tensor<1,spacedim> > patch_gradients;
- std::vector<std::vector<Tensor<1,spacedim> > > patch_gradients_system;
- std::vector<Tensor<2,spacedim> > patch_hessians;
- std::vector<std::vector<Tensor<2,spacedim> > > patch_hessians_system;
- std::vector<std::vector<dealii::Vector<double> > > postprocessed_values;
-
- const dealii::hp::MappingCollection<dim,spacedim> mapping_collection;
- const std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<dim,spacedim> > > finite_elements;
- const UpdateFlags update_flags;
-
- std::vector<std_cxx1x::shared_ptr<dealii::hp::FEValues<dim,spacedim> > > x_fe_values;
- std::vector<std_cxx1x::shared_ptr<dealii::hp::FEFaceValues<dim,spacedim> > > 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
}
-//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 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.
- *
- *
- * <h3>User visible interface</h3>
- *
- * 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
- * ...
- * ... // compute error_estimator, which contains one value per cell
- *
- * std::vector<std::string> solution_names;
- * solution_names.push_back ("x-displacement");
- * solution_names.push_back ("y-displacement");
- *
- * DataOut<dim> data_out;
- * data_out.attach_dof_handler (dof_handler);
- * data_out.add_data_vector (solution, solution_names);
- * data_out.add_data_vector (error_estimator, "estimated_error");
- *
- * data_out.build_patches ();
- *
- * ofstream output_file ("output");
- * data_out.write_xxx (output_file);
- *
- * data_out.clear();
- * @endcode
- *
- * attach_dof_handler() tells this class that all future operations
- * are to take place with the DoFHandler object and the triangulation
- * it lives on. We then add the solution vector and the error
- * estimator; note that they have different dimensions, because the
- * solution is a nodal vector, here consisting of two components
- * ("x-displacement" and "y-displacement") while the error estimator
- * probably is a vector holding cell data. When attaching a data
- * vector, you have to give a name to each component of the vector,
- * which is done through an object of type <tt>vector<string></tt> as
- * second argument; if only one component is in the vector, for
- * example if we are adding cell data as in the second case, or if the
- * finite element used by the DoFHandler has only one component, then
- * you can use the second add_data_vector() function which takes a @p
- * string instead of the <tt>vector<string></tt>.
- *
- * The add_data_vector() functions have additional arguments (with default
- * values) that can be used to specify certain transformations. In particular,
- * it allows to attach DataPostprocessor arguments to compute derived
- * information from a data vector at each point at which the field will
- * be evaluated so that it can be written to a file (for example, the
- * Mach number in hypersonic flow can be computed from density and velocities;
- * step-29 also shows an example); another piece of information
- * specified through arguments with default values is how certain output
- * components should be interpreted, i.e. whether each component of the data
- * is logically an independent scalar field, or whether some of them together
- * form logically a vector-field (see the
- * DataComponentInterpretation::DataComponentInterpretation enum, and the @ref
- * step_22 "step-22" tutorial program).
- *
- * It should be noted that this class does not copy the vector given to it through
- * the add_data_vector() functions, for memory consumption reasons. It only
- * stores a reference to it, so it is in your responsibility to make sure that
- * the data vectors exist long enough.
- *
- * After adding all data vectors, you need to call a function which generates
- * the patches for output from the stored data. Derived classes name this
- * 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
- * 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.
- *
- * Note that the base class of this class, DataOutInterface offers
- * several functions to ease programming with run-time determinable
- * output formats (i.e. you need not use a fixed format by calling
- * DataOutInterface::write_xxx in the above example, but you can
- * select it by a run-time parameter without having to write the
- * <tt>if () ... else ...</tt> clauses yourself), and also functions
- * and classes offering ways to control the appearance of the output
- * by setting flags for each output format.
- *
- *
- * <h3>Information for derived classes</h3>
- *
- * What is actually missing this class is a way to produce the patches
- * for output itself, from the stored data and degree of freedom
- * information. Since this task is often application dependent it is
- * left to derived classes. For example, in many applications, it
- * might be wanted to limit the depth of output to a certain number of
- * refinement levels and write data from finer cells only in a way
- * interpolated to coarser cells, to reduce the amount of
- * output. Also, it might be wanted to use different numbers of
- * subdivisions on different cells when forming a patch, for example
- * to accomplish for different polynomial degrees of the trial space
- * on different cells. Also, the output need not necessarily consist
- * of a patch for each cell, but might be made up of patches for
- * faces, of other things. Take a look at derived classes to what is
- * possible in this respect.
- *
- * For this reason, it is left to a derived class to provide a
- * function, named usually build_patches() or the like, which fills
- * the #patches array of this class.
- *
- * Regarding the templates of this class, it needs three values: first
- * the space dimension in which the triangulation and the DoF handler
- * operate, second the dimension of the objects which the patches
- * represent. Although in most cases they are equal, there are also
- * classes for which this does not hold, for example if one outputs
- * the result of a computation exploiting rotational symmetry in the
- * original domain (in which the space dimension of the output would
- * be one higher than that of the DoF handler, see the
- * DataOut_Rotation() class), or one might conceive that one could
- * write a class that only outputs the solution on a cut through the
- * domain, in which case the space dimension of the output is less
- * than that of the DoF handler. The last template argument denotes
- * the dimension of the space into which the patches are embedded;
- * usually, this dimension is the same as the dimensio of the patches
- * themselves (which is also the default value of the template
- * parameter), but there might be cases where this is not so. For
- * example, in the DataOut_Faces() class, patches are generated
- * from faces of the triangulation. Thus, the dimension of the patch
- * is one less than the dimension of the embedding space, which is, in
- * this case, equal to the dimension of the triangulation and DoF
- * handler. However, for the cut through the domain mentioned above,
- * if the cut is a straight one, then the cut can be embedded into a
- * space of one dimension lower than the dimension of the
- * triangulation, so that the last template parameter has the same
- * value as the second one.
- *
- * @ingroup output
- * @author Wolfgang Bangerth, 1999
- */
-template <class DH, int patch_dim, int patch_space_dim=patch_dim>
-class DataOut_DoFData : public DataOutInterface<patch_dim,patch_space_dim>
-{
-public:
-
- /**
- * Typedef to the iterator type of the dof handler class under
- * consideration.
- */
- typedef typename Triangulation<DH::dimension,DH::space_dimension>::cell_iterator cell_iterator;
- typedef typename Triangulation<DH::dimension,DH::space_dimension>::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).
- */
- enum DataVectorType
- {
- /**
- * Data vector entries are associated to degrees of freedom
- */
- type_dof_data,
-
- /**
- * Data vector entries are one per grid cell
- */
- type_cell_data,
-
- /**
- * Find out automatically
- */
- type_automatic
- };
-
- /**
- * Constructor
- */
- DataOut_DoFData ();
-
- /**
- * Destructor.
- */
- virtual ~DataOut_DoFData ();
-
- /**
- * 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 &);
-
- /**
- * Designate a triangulation to be used to extract geometry data and the
- * mapping between nodes and node values.
- *
- * 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<DH::dimension,
- DH::space_dimension> &);
-
- /**
- * 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 <tt>write_*</tt>
- * 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.
- *
- * 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.
- *
- * 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
- * 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_part_of_vector,
- * DataComponentInterpretation::component_is_part_of_vector,
- * 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.
- *
- * @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 <class VECTOR>
- void add_data_vector (const VECTOR &data,
- const std::vector<std::string> &names,
- const DataVectorType type = type_automatic,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation
- = std::vector<DataComponentInterpretation::DataComponentInterpretation>());
-
- /**
- * 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
- *
- * 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 <class VECTOR>
- void add_data_vector (const VECTOR &data,
- const std::string &name,
- const DataVectorType type = type_automatic,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation
- = std::vector<DataComponentInterpretation::DataComponentInterpretation>());
-
- /**
- * 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 <class VECTOR>
- void add_data_vector (const DH &dof_handler,
- const VECTOR &data,
- const std::vector<std::string> &names,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation
- = std::vector<DataComponentInterpretation::DataComponentInterpretation>());
-
-
- /**
- * This function is an abbreviation of the function above with only a scalar
- * @p dof_handler given and a single data name.
- */
- template <class VECTOR>
- void add_data_vector (const DH &dof_handler,
- const VECTOR &data,
- const std::string &name,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation
- = std::vector<DataComponentInterpretation::DataComponentInterpretation>());
-
- /**
- * 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.
- *
- * @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 <class VECTOR>
- void add_data_vector (const VECTOR &data,
- const DataPostprocessor<DH::space_dimension> &data_postprocessor);
-
- /**
- * 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 <class VECTOR>
- void add_data_vector (const DH &dof_handler,
- const VECTOR &data,
- const DataPostprocessor<DH::space_dimension> &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.
- */
- 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.
- *
- * 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.
- *
- * 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.
- */
- template <class DH2>
- void merge_patches (const DataOut_DoFData<DH2,patch_dim,patch_space_dim> &source,
- const Point<patch_space_dim> &shift = Point<patch_space_dim>());
-
- /**
- * 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.
- */
- std::size_t memory_consumption () const;
-
- /**
- * Exception
- */
- DeclException0 (ExcNoTriangulationSelected);
-
- /**
- * Exception
- */
- DeclException0 (ExcNoDoFHandlerSelected);
-
- /**
- * Exception
- */
- DeclException0 (ExcDataPostprocessingIsNotPossibleForCellData);
-
- /**
- * Exception
- */
- DeclException3 (ExcInvalidVectorSize,
- int, int, int,
- << "The vector has size " << arg1
- << " but the DoFHandler objects says there are " << arg2
- << " degrees of freedom and there are " << arg3
- << " active cells.");
- /**
- * Exception
- */
- DeclException2 (ExcInvalidCharacter,
- std::string, size_t,
- << "Please use only the characters [a-zA-Z0-9_<>()] for" << std::endl
- << "description strings since some graphics formats will only accept these."
- << std::endl
- << "The string you gave was <" << arg1
- << ">, the invalid character is <" << arg1[arg2]
- << ">." << std::endl);
- /**
- * Exception
- */
- DeclException0 (ExcOldDataStillPresent);
- /**
- * Exception
- */
- DeclException2 (ExcInvalidNumberOfNames,
- int, int,
- << "You have to give one name per component in your "
- << "data vector. The number you gave was " << arg1
- << ", but the number of components is " << arg2);
- /**
- * Exception
- */
- DeclException0 (ExcNoPatches);
- /**
- * Exception
- */
- DeclException0 (ExcIncompatibleDatasetNames);
- /**
- * Exception
- */
- DeclException0 (ExcIncompatiblePatchLists);
-
- DeclException2 (ExcInvalidVectorDeclaration,
- int, std::string,
- << "When declaring that a number of components in a data\n"
- << "set to be output logically form a vector instead of\n"
- << "simply a set of scalar fields, you need to specify\n"
- << "this for all relevant components. Furthermore,\n"
- << "vectors must always consist of exactly <dim>\n"
- << "components. However, the vector component at\n"
- << "position " << arg1 << " with name <" << arg2
- << "> does not satisfy these conditions.");
-
-protected:
- /**
- * Abbreviate the somewhat lengthy name for the Patch class.
- */
- typedef dealii::DataOutBase::Patch<patch_dim,patch_space_dim> Patch;
-
- /**
- * Pointer to the triangulation object.
- */
- SmartPointer<const Triangulation<DH::dimension,DH::space_dimension> > triangulation;
-
- /**
- * Pointer to the optional handler object.
- */
- SmartPointer<const DH> dofs;
-
- /**
- * List of data elements with vectors of values for each degree of freedom.
- */
- std::vector<std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> > > dof_data;
-
- /**
- * List of data elements with vectors of values for each cell.
- */
- std::vector<std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> > > 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
- * classes.
- */
- std::vector<Patch> patches;
-
- /**
- * Function by which the base class's functions get to know what patches
- * they shall write to a file.
- */
- virtual
- const std::vector<Patch> &get_patches () const;
-
- /**
- * Virtual function through which the names of data sets are obtained by the
- * output functions of the base class.
- */
- virtual
- std::vector<std::string> get_dataset_names () const;
-
- /**
- * Extracts the finite elements stored in the dof_data object, including a
- * dummy object of FE_DGQ<dim>(0) in case only the triangulation is used.
- */
- std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<DH::dimension,DH::space_dimension> > >
- get_finite_elements() const;
-
- /**
- * Overload of the respective DataOutInterface::get_vector_data_ranges()
- * function. See there for a more extensive documentation.
- */
- virtual
- std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >
- get_vector_data_ranges () const;
-
- /**
- * Make all template siblings friends. Needed for the merge_patches()
- * function.
- */
- template <class, int, int>
- friend class DataOut_DoFData;
-};
-
-
/**
* This class is the main class to provide output of data described by finite
-// -------------------- template and inline functions ------------------------
-
-
-template <class DH, int patch_dim, int patch_space_dim>
-template <class DH2>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-merge_patches (const DataOut_DoFData<DH2,patch_dim,patch_space_dim> &source,
- const Point<patch_space_dim> &shift)
-{
- const std::vector<Patch> source_patches = source.get_patches ();
- Assert (patches.size () != 0, ExcNoPatches ());
- Assert (source_patches.size () != 0, ExcNoPatches ());
- // check equality of component
- // names
- Assert (get_dataset_names() == source.get_dataset_names(),
- ExcIncompatibleDatasetNames());
- // make sure patches are compatible. we'll
- // assume that if the first respective
- // patches are ok that all the other ones
- // are ok as well
- Assert (patches[0].n_subdivisions == source_patches[0].n_subdivisions,
- ExcIncompatiblePatchLists());
- Assert (patches[0].data.n_rows() == source_patches[0].data.n_rows(),
- ExcIncompatiblePatchLists());
- Assert (patches[0].data.n_cols() == source_patches[0].data.n_cols(),
- ExcIncompatiblePatchLists());
-
- // check equality of the vector data
- // specifications
- Assert (get_vector_data_ranges().size() ==
- source.get_vector_data_ranges().size(),
- ExcMessage ("Both sources need to declare the same components "
- "as vectors."));
- for (unsigned int i=0; i<get_vector_data_ranges().size(); ++i)
- {
- Assert (std_cxx1x::get<0>(get_vector_data_ranges()[i]) ==
- std_cxx1x::get<0>(source.get_vector_data_ranges()[i]),
- ExcMessage ("Both sources need to declare the same components "
- "as vectors."));
- Assert (std_cxx1x::get<1>(get_vector_data_ranges()[i]) ==
- std_cxx1x::get<1>(source.get_vector_data_ranges()[i]),
- ExcMessage ("Both sources need to declare the same components "
- "as vectors."));
- Assert (std_cxx1x::get<2>(get_vector_data_ranges()[i]) ==
- std_cxx1x::get<2>(source.get_vector_data_ranges()[i]),
- ExcMessage ("Both sources need to declare the same components "
- "as vectors."));
- }
-
- // merge patches. store old number
- // of elements, since we need to
- // adjust patch numbers, etc
- // afterwards
- const unsigned int old_n_patches = patches.size();
- patches.insert (patches.end(),
- source_patches.begin(),
- source_patches.end());
-
- // perform shift, if so desired
- if (shift != Point<patch_space_dim>())
- for (unsigned int i=old_n_patches; i<patches.size(); ++i)
- for (unsigned int v=0; v<GeometryInfo<patch_dim>::vertices_per_cell; ++v)
- patches[i].vertices[v] += shift;
-
- // adjust patch numbers
- for (unsigned int i=old_n_patches; i<patches.size(); ++i)
- patches[i].patch_index += old_n_patches;
-
- // adjust patch neighbors
- for (unsigned int i=old_n_patches; i<patches.size(); ++i)
- for (unsigned int n=0; n<GeometryInfo<patch_dim>::faces_per_cell; ++n)
- if (patches[i].neighbors[n] != Patch::no_neighbor)
- patches[i].neighbors[n] += old_n_patches;
-}
-
-
DEAL_II_NAMESPACE_CLOSE
#endif
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__data_out_dof_data_h
+#define __deal2__data_out_dof_data_h
+
+
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/smartpointer.h>
+#include <deal.II/base/data_out_base.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/fe/mapping.h>
+#include <deal.II/hp/q_collection.h>
+#include <deal.II/hp/fe_collection.h>
+#include <deal.II/hp/mapping_collection.h>
+#include <deal.II/hp/fe_values.h>
+#include <deal.II/numerics/data_postprocessor.h>
+#include <deal.II/numerics/data_component_interpretation.h>
+
+#include <deal.II/base/std_cxx1x/shared_ptr.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+template <int, int> class FEValuesBase;
+
+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.
+ *
+ * @author Wolfgang Bangerth, 2004
+ */
+ template <class DH>
+ class DataEntryBase
+ {
+ 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.
+ */
+ DataEntryBase (const DH *dofs,
+ const std::vector<std::string> &names,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &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.
+ */
+ DataEntryBase (const DH *dofs,
+ const DataPostprocessor<DH::space_dimension> *data_postprocessor);
+
+ /**
+ * Destructor made virtual.
+ */
+ virtual ~DataEntryBase ();
+
+ /**
+ * Assuming that the stored vector is a cell vector, extract the given
+ * element from it.
+ */
+ virtual
+ double
+ 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.
+ */
+ virtual
+ void
+ get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<double> &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.
+ */
+ virtual
+ void
+ get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<dealii::Vector<double> > &patch_values_system) const = 0;
+
+ /**
+ * Given a FEValuesBase object, extract the gradients on the present
+ * cell from the vector we actually store.
+ */
+ virtual
+ void
+ get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<Tensor<1,DH::space_dimension> > &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.
+ */
+ virtual
+ void
+ get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<std::vector<Tensor<1,DH::space_dimension> > > &patch_gradients_system) const = 0;
+
+ /**
+ * Given a FEValuesBase object, extract the second derivatives on the
+ * present cell from the vector we actually store.
+ */
+ virtual
+ void
+ get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<Tensor<2,DH::space_dimension> > &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.
+ */
+ virtual
+ void
+ get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<std::vector< Tensor<2,DH::space_dimension> > > &patch_hessians_system) const = 0;
+
+ /**
+ * Clear all references to the vectors.
+ */
+ virtual void clear () = 0;
+
+ /**
+ * Determine an estimate for the memory consumption (in bytes) of this
+ * object.
+ */
+ virtual std::size_t memory_consumption () const = 0;
+
+ /**
+ * Pointer to the DoFHandler object that the vector is based on.
+ */
+ SmartPointer<const DH> dof_handler;
+
+ /**
+ * Names of the components of this data vector.
+ */
+ const std::vector<std::string> 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.
+ */
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation>
+ data_component_interpretation;
+
+ /**
+ * Pointer to a DataPostprocessing object which shall be applied to this
+ * data vector.
+ */
+ SmartPointer<const dealii::DataPostprocessor<DH::space_dimension> > 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 <tt>names.size()</tt>.
+ */
+ 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.
+ *
+ * The <code>cell_to_patch_index_map</code> is an array that stores for
+ * index <tt>[i][j]</tt> 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.
+ */
+ template <int dim, int spacedim>
+ struct ParallelDataBase
+ {
+ ParallelDataBase (const unsigned int n_datasets,
+ const unsigned int n_subdivisions,
+ const std::vector<unsigned int> &n_postprocessor_outputs,
+ const Mapping<dim,spacedim> &mapping,
+ const std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<dim,spacedim> > > &finite_elements,
+ const UpdateFlags update_flags,
+ const bool use_face_values);
+
+ ParallelDataBase (const ParallelDataBase &data);
+
+ template <typename DH>
+ void reinit_all_fe_values(std::vector<std_cxx1x::shared_ptr<DataEntryBase<DH> > > &dof_data,
+ const typename dealii::Triangulation<dim,spacedim>::cell_iterator &cell,
+ const unsigned int face = numbers::invalid_unsigned_int);
+
+ const FEValuesBase<dim,spacedim> &
+ get_present_fe_values(const unsigned int dataset) const;
+
+ void resize_system_vectors(const unsigned int n_components);
+
+ const unsigned int n_datasets;
+ const unsigned int n_subdivisions;
+
+ std::vector<double> patch_values;
+ std::vector<dealii::Vector<double> > patch_values_system;
+ std::vector<Tensor<1,spacedim> > patch_gradients;
+ std::vector<std::vector<Tensor<1,spacedim> > > patch_gradients_system;
+ std::vector<Tensor<2,spacedim> > patch_hessians;
+ std::vector<std::vector<Tensor<2,spacedim> > > patch_hessians_system;
+ std::vector<std::vector<dealii::Vector<double> > > postprocessed_values;
+
+ const dealii::hp::MappingCollection<dim,spacedim> mapping_collection;
+ const std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<dim,spacedim> > > finite_elements;
+ const UpdateFlags update_flags;
+
+ std::vector<std_cxx1x::shared_ptr<dealii::hp::FEValues<dim,spacedim> > > x_fe_values;
+ std::vector<std_cxx1x::shared_ptr<dealii::hp::FEFaceValues<dim,spacedim> > > x_fe_face_values;
+ };
+ }
+}
+
+
+//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 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.
+ *
+ *
+ * <h3>User visible interface</h3>
+ *
+ * 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
+ * ...
+ * ... // compute error_estimator, which contains one value per cell
+ *
+ * std::vector<std::string> solution_names;
+ * solution_names.push_back ("x-displacement");
+ * solution_names.push_back ("y-displacement");
+ *
+ * DataOut<dim> data_out;
+ * data_out.attach_dof_handler (dof_handler);
+ * data_out.add_data_vector (solution, solution_names);
+ * data_out.add_data_vector (error_estimator, "estimated_error");
+ *
+ * data_out.build_patches ();
+ *
+ * ofstream output_file ("output");
+ * data_out.write_xxx (output_file);
+ *
+ * data_out.clear();
+ * @endcode
+ *
+ * attach_dof_handler() tells this class that all future operations
+ * are to take place with the DoFHandler object and the triangulation
+ * it lives on. We then add the solution vector and the error
+ * estimator; note that they have different dimensions, because the
+ * solution is a nodal vector, here consisting of two components
+ * ("x-displacement" and "y-displacement") while the error estimator
+ * probably is a vector holding cell data. When attaching a data
+ * vector, you have to give a name to each component of the vector,
+ * which is done through an object of type <tt>vector<string></tt> as
+ * second argument; if only one component is in the vector, for
+ * example if we are adding cell data as in the second case, or if the
+ * finite element used by the DoFHandler has only one component, then
+ * you can use the second add_data_vector() function which takes a @p
+ * string instead of the <tt>vector<string></tt>.
+ *
+ * The add_data_vector() functions have additional arguments (with default
+ * values) that can be used to specify certain transformations. In particular,
+ * it allows to attach DataPostprocessor arguments to compute derived
+ * information from a data vector at each point at which the field will
+ * be evaluated so that it can be written to a file (for example, the
+ * Mach number in hypersonic flow can be computed from density and velocities;
+ * step-29 also shows an example); another piece of information
+ * specified through arguments with default values is how certain output
+ * components should be interpreted, i.e. whether each component of the data
+ * is logically an independent scalar field, or whether some of them together
+ * form logically a vector-field (see the
+ * DataComponentInterpretation::DataComponentInterpretation enum, and the @ref
+ * step_22 "step-22" tutorial program).
+ *
+ * It should be noted that this class does not copy the vector given to it through
+ * the add_data_vector() functions, for memory consumption reasons. It only
+ * stores a reference to it, so it is in your responsibility to make sure that
+ * the data vectors exist long enough.
+ *
+ * After adding all data vectors, you need to call a function which generates
+ * the patches for output from the stored data. Derived classes name this
+ * 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
+ * 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.
+ *
+ * Note that the base class of this class, DataOutInterface offers
+ * several functions to ease programming with run-time determinable
+ * output formats (i.e. you need not use a fixed format by calling
+ * DataOutInterface::write_xxx in the above example, but you can
+ * select it by a run-time parameter without having to write the
+ * <tt>if () ... else ...</tt> clauses yourself), and also functions
+ * and classes offering ways to control the appearance of the output
+ * by setting flags for each output format.
+ *
+ *
+ * <h3>Information for derived classes</h3>
+ *
+ * What is actually missing this class is a way to produce the patches
+ * for output itself, from the stored data and degree of freedom
+ * information. Since this task is often application dependent it is
+ * left to derived classes. For example, in many applications, it
+ * might be wanted to limit the depth of output to a certain number of
+ * refinement levels and write data from finer cells only in a way
+ * interpolated to coarser cells, to reduce the amount of
+ * output. Also, it might be wanted to use different numbers of
+ * subdivisions on different cells when forming a patch, for example
+ * to accomplish for different polynomial degrees of the trial space
+ * on different cells. Also, the output need not necessarily consist
+ * of a patch for each cell, but might be made up of patches for
+ * faces, of other things. Take a look at derived classes to what is
+ * possible in this respect.
+ *
+ * For this reason, it is left to a derived class to provide a
+ * function, named usually build_patches() or the like, which fills
+ * the #patches array of this class.
+ *
+ * Regarding the templates of this class, it needs three values: first
+ * the space dimension in which the triangulation and the DoF handler
+ * operate, second the dimension of the objects which the patches
+ * represent. Although in most cases they are equal, there are also
+ * classes for which this does not hold, for example if one outputs
+ * the result of a computation exploiting rotational symmetry in the
+ * original domain (in which the space dimension of the output would
+ * be one higher than that of the DoF handler, see the
+ * DataOut_Rotation() class), or one might conceive that one could
+ * write a class that only outputs the solution on a cut through the
+ * domain, in which case the space dimension of the output is less
+ * than that of the DoF handler. The last template argument denotes
+ * the dimension of the space into which the patches are embedded;
+ * usually, this dimension is the same as the dimensio of the patches
+ * themselves (which is also the default value of the template
+ * parameter), but there might be cases where this is not so. For
+ * example, in the DataOut_Faces() class, patches are generated
+ * from faces of the triangulation. Thus, the dimension of the patch
+ * is one less than the dimension of the embedding space, which is, in
+ * this case, equal to the dimension of the triangulation and DoF
+ * handler. However, for the cut through the domain mentioned above,
+ * if the cut is a straight one, then the cut can be embedded into a
+ * space of one dimension lower than the dimension of the
+ * triangulation, so that the last template parameter has the same
+ * value as the second one.
+ *
+ * @ingroup output
+ * @author Wolfgang Bangerth, 1999
+ */
+template <class DH, int patch_dim, int patch_space_dim=patch_dim>
+class DataOut_DoFData : public DataOutInterface<patch_dim,patch_space_dim>
+{
+public:
+
+ /**
+ * Typedef to the iterator type of the dof handler class under
+ * consideration.
+ */
+ typedef typename Triangulation<DH::dimension,DH::space_dimension>::cell_iterator cell_iterator;
+ typedef typename Triangulation<DH::dimension,DH::space_dimension>::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).
+ */
+ enum DataVectorType
+ {
+ /**
+ * Data vector entries are associated to degrees of freedom
+ */
+ type_dof_data,
+
+ /**
+ * Data vector entries are one per grid cell
+ */
+ type_cell_data,
+
+ /**
+ * Find out automatically
+ */
+ type_automatic
+ };
+
+ /**
+ * Constructor
+ */
+ DataOut_DoFData ();
+
+ /**
+ * Destructor.
+ */
+ virtual ~DataOut_DoFData ();
+
+ /**
+ * 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 &);
+
+ /**
+ * Designate a triangulation to be used to extract geometry data and the
+ * mapping between nodes and node values.
+ *
+ * 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<DH::dimension,
+ DH::space_dimension> &);
+
+ /**
+ * 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 <tt>write_*</tt>
+ * 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.
+ *
+ * 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.
+ *
+ * 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
+ * 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_part_of_vector,
+ * DataComponentInterpretation::component_is_part_of_vector,
+ * 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.
+ *
+ * @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 <class VECTOR>
+ void add_data_vector (const VECTOR &data,
+ const std::vector<std::string> &names,
+ const DataVectorType type = type_automatic,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation
+ = std::vector<DataComponentInterpretation::DataComponentInterpretation>());
+
+ /**
+ * 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
+ *
+ * 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 <class VECTOR>
+ void add_data_vector (const VECTOR &data,
+ const std::string &name,
+ const DataVectorType type = type_automatic,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation
+ = std::vector<DataComponentInterpretation::DataComponentInterpretation>());
+
+ /**
+ * 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 <class VECTOR>
+ void add_data_vector (const DH &dof_handler,
+ const VECTOR &data,
+ const std::vector<std::string> &names,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation
+ = std::vector<DataComponentInterpretation::DataComponentInterpretation>());
+
+
+ /**
+ * This function is an abbreviation of the function above with only a scalar
+ * @p dof_handler given and a single data name.
+ */
+ template <class VECTOR>
+ void add_data_vector (const DH &dof_handler,
+ const VECTOR &data,
+ const std::string &name,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation
+ = std::vector<DataComponentInterpretation::DataComponentInterpretation>());
+
+ /**
+ * 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.
+ *
+ * @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 <class VECTOR>
+ void add_data_vector (const VECTOR &data,
+ const DataPostprocessor<DH::space_dimension> &data_postprocessor);
+
+ /**
+ * 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 <class VECTOR>
+ void add_data_vector (const DH &dof_handler,
+ const VECTOR &data,
+ const DataPostprocessor<DH::space_dimension> &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.
+ */
+ 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.
+ *
+ * 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.
+ *
+ * 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.
+ */
+ template <class DH2>
+ void merge_patches (const DataOut_DoFData<DH2,patch_dim,patch_space_dim> &source,
+ const Point<patch_space_dim> &shift = Point<patch_space_dim>());
+
+ /**
+ * 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.
+ */
+ std::size_t memory_consumption () const;
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNoTriangulationSelected);
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNoDoFHandlerSelected);
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcDataPostprocessingIsNotPossibleForCellData);
+
+ /**
+ * Exception
+ */
+ DeclException3 (ExcInvalidVectorSize,
+ int, int, int,
+ << "The vector has size " << arg1
+ << " but the DoFHandler objects says there are " << arg2
+ << " degrees of freedom and there are " << arg3
+ << " active cells.");
+ /**
+ * Exception
+ */
+ DeclException2 (ExcInvalidCharacter,
+ std::string, size_t,
+ << "Please use only the characters [a-zA-Z0-9_<>()] for" << std::endl
+ << "description strings since some graphics formats will only accept these."
+ << std::endl
+ << "The string you gave was <" << arg1
+ << ">, the invalid character is <" << arg1[arg2]
+ << ">." << std::endl);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcOldDataStillPresent);
+ /**
+ * Exception
+ */
+ DeclException2 (ExcInvalidNumberOfNames,
+ int, int,
+ << "You have to give one name per component in your "
+ << "data vector. The number you gave was " << arg1
+ << ", but the number of components is " << arg2);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNoPatches);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcIncompatibleDatasetNames);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcIncompatiblePatchLists);
+
+ DeclException2 (ExcInvalidVectorDeclaration,
+ int, std::string,
+ << "When declaring that a number of components in a data\n"
+ << "set to be output logically form a vector instead of\n"
+ << "simply a set of scalar fields, you need to specify\n"
+ << "this for all relevant components. Furthermore,\n"
+ << "vectors must always consist of exactly <dim>\n"
+ << "components. However, the vector component at\n"
+ << "position " << arg1 << " with name <" << arg2
+ << "> does not satisfy these conditions.");
+
+protected:
+ /**
+ * Abbreviate the somewhat lengthy name for the Patch class.
+ */
+ typedef dealii::DataOutBase::Patch<patch_dim,patch_space_dim> Patch;
+
+ /**
+ * Pointer to the triangulation object.
+ */
+ SmartPointer<const Triangulation<DH::dimension,DH::space_dimension> > triangulation;
+
+ /**
+ * Pointer to the optional handler object.
+ */
+ SmartPointer<const DH> dofs;
+
+ /**
+ * List of data elements with vectors of values for each degree of freedom.
+ */
+ std::vector<std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> > > dof_data;
+
+ /**
+ * List of data elements with vectors of values for each cell.
+ */
+ std::vector<std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> > > 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
+ * classes.
+ */
+ std::vector<Patch> patches;
+
+ /**
+ * Function by which the base class's functions get to know what patches
+ * they shall write to a file.
+ */
+ virtual
+ const std::vector<Patch> &get_patches () const;
+
+ /**
+ * Virtual function through which the names of data sets are obtained by the
+ * output functions of the base class.
+ */
+ virtual
+ std::vector<std::string> get_dataset_names () const;
+
+ /**
+ * Extracts the finite elements stored in the dof_data object, including a
+ * dummy object of FE_DGQ<dim>(0) in case only the triangulation is used.
+ */
+ std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<DH::dimension,DH::space_dimension> > >
+ get_finite_elements() const;
+
+ /**
+ * Overload of the respective DataOutInterface::get_vector_data_ranges()
+ * function. See there for a more extensive documentation.
+ */
+ virtual
+ std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >
+ get_vector_data_ranges () const;
+
+ /**
+ * Make all template siblings friends. Needed for the merge_patches()
+ * function.
+ */
+ template <class, int, int>
+ friend class DataOut_DoFData;
+};
+
+
+
+// -------------------- template and inline functions ------------------------
+
+
+template <class DH, int patch_dim, int patch_space_dim>
+template <class DH2>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+merge_patches (const DataOut_DoFData<DH2,patch_dim,patch_space_dim> &source,
+ const Point<patch_space_dim> &shift)
+{
+ const std::vector<Patch> source_patches = source.get_patches ();
+ Assert (patches.size () != 0, ExcNoPatches ());
+ Assert (source_patches.size () != 0, ExcNoPatches ());
+ // check equality of component
+ // names
+ Assert (get_dataset_names() == source.get_dataset_names(),
+ ExcIncompatibleDatasetNames());
+ // make sure patches are compatible. we'll
+ // assume that if the first respective
+ // patches are ok that all the other ones
+ // are ok as well
+ Assert (patches[0].n_subdivisions == source_patches[0].n_subdivisions,
+ ExcIncompatiblePatchLists());
+ Assert (patches[0].data.n_rows() == source_patches[0].data.n_rows(),
+ ExcIncompatiblePatchLists());
+ Assert (patches[0].data.n_cols() == source_patches[0].data.n_cols(),
+ ExcIncompatiblePatchLists());
+
+ // check equality of the vector data
+ // specifications
+ Assert (get_vector_data_ranges().size() ==
+ source.get_vector_data_ranges().size(),
+ ExcMessage ("Both sources need to declare the same components "
+ "as vectors."));
+ for (unsigned int i=0; i<get_vector_data_ranges().size(); ++i)
+ {
+ Assert (std_cxx1x::get<0>(get_vector_data_ranges()[i]) ==
+ std_cxx1x::get<0>(source.get_vector_data_ranges()[i]),
+ ExcMessage ("Both sources need to declare the same components "
+ "as vectors."));
+ Assert (std_cxx1x::get<1>(get_vector_data_ranges()[i]) ==
+ std_cxx1x::get<1>(source.get_vector_data_ranges()[i]),
+ ExcMessage ("Both sources need to declare the same components "
+ "as vectors."));
+ Assert (std_cxx1x::get<2>(get_vector_data_ranges()[i]) ==
+ std_cxx1x::get<2>(source.get_vector_data_ranges()[i]),
+ ExcMessage ("Both sources need to declare the same components "
+ "as vectors."));
+ }
+
+ // merge patches. store old number
+ // of elements, since we need to
+ // adjust patch numbers, etc
+ // afterwards
+ const unsigned int old_n_patches = patches.size();
+ patches.insert (patches.end(),
+ source_patches.begin(),
+ source_patches.end());
+
+ // perform shift, if so desired
+ if (shift != Point<patch_space_dim>())
+ for (unsigned int i=old_n_patches; i<patches.size(); ++i)
+ for (unsigned int v=0; v<GeometryInfo<patch_dim>::vertices_per_cell; ++v)
+ patches[i].vertices[v] += shift;
+
+ // adjust patch numbers
+ for (unsigned int i=old_n_patches; i<patches.size(); ++i)
+ patches[i].patch_index += old_n_patches;
+
+ // adjust patch neighbors
+ for (unsigned int i=old_n_patches; i<patches.size(); ++i)
+ for (unsigned int n=0; n<GeometryInfo<patch_dim>::faces_per_cell; ++n)
+ if (patches[i].neighbors[n] != Patch::no_neighbor)
+ patches[i].neighbors[n] += old_n_patches;
+}
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
#include <deal.II/base/config.h>
-#include <deal.II/numerics/data_out.h>
+#include <deal.II/numerics/data_out_dof_data.h>
#include <string>
#include <vector>
{
public:
/**
- * Implementation of the error
- * estimator described above. You
- * may give a coefficient, but
- * there is a default value which
- * denotes the constant
- * coefficient with value
- * one. The coefficient function
- * may either be a scalar one, in
- * which case it is used for all
- * components of the finite
- * element, or a vector-valued
- * one with as many components as
- * there are in the finite
- * element; in the latter case,
- * each component is weighted by
- * the respective component in
- * the coefficient.
+ * Implementation of the error estimator described above. You may give a
+ * coefficient, but there is a default value which denotes the constant
+ * coefficient with value one. The coefficient function may either be a
+ * scalar one, in which case it is used for all components of the finite
+ * element, or a vector-valued one with as many components as there are in
+ * the finite element; in the latter case, each component is weighted by the
+ * respective component in the coefficient.
*
- * You might give a list of
- * components you want to
- * evaluate, in case the finite
- * element used by the
- * DoFHandler object is
- * vector-valued. You then have
- * to set those entries to true
- * in the bit-vector
- * @p component_mask
- * (see @ref GlossComponentMask)
- * for which the
- * respective component is to be
- * used in the error
- * estimator. The default is to
- * use all components, which is
- * done by either providing a
- * bit-vector with all-set
- * entries, or an empty
- * bit-vector.
+ * You might give a list of components you want to evaluate, in case the
+ * finite element used by the DoFHandler object is vector-valued. You then
+ * have to set those entries to true in the bit-vector @p component_mask
+ * (see @ref GlossComponentMask) for which the respective component is to be
+ * used in the error estimator. The default is to use all components, which
+ * is done by either providing a bit-vector with all-set entries, or an
+ * empty bit-vector.
*
- * The @p subdomain_id parameter
- * indicates whether we shall compute
- * indicators for all cells (in case its
- * value is the default,
- * <tt>numbers::invalid_unsigned_int</tt>),
- * or only for the cells belonging to a
- * certain subdomain with the given
- * indicator. The latter case is used for
- * parallel computations where all
- * processor nodes have the global grid
- * stored, and could well compute all the
- * indicators for all cells themselves,
- * but where it is more efficient to have
- * each process compute only indicators
- * for the cells it owns, and have them
- * exchange the resulting information
- * afterwards. This is in particular true
- * for the case where meshes are very
- * large and computing indicators for @em
- * every cell is too expensive, while
- * computing indicators for only local
- * cells is acceptable. Note that if you
- * only ask for the indicators of a
- * certain subdomain to be computed, you
- * must nevertheless make sure that this
- * function has access to the correct
- * node values of @em all degrees of
- * freedom. This is since the function
- * needs to access DoF values on
- * neighboring cells as well, even if
- * they belong to a different subdomain.
+ * The @p subdomain_id parameter indicates whether we shall compute
+ * indicators for all cells (in case its value is the default,
+ * <tt>numbers::invalid_unsigned_int</tt>), or only for the cells belonging
+ * to a certain subdomain with the given indicator. The latter case is used
+ * for parallel computations where all processor nodes have the global grid
+ * stored, and could well compute all the indicators for all cells
+ * themselves, but where it is more efficient to have each process compute
+ * only indicators for the cells it owns, and have them exchange the
+ * resulting information afterwards. This is in particular true for the case
+ * where meshes are very large and computing indicators for @em every cell
+ * is too expensive, while computing indicators for only local cells is
+ * acceptable. Note that if you only ask for the indicators of a certain
+ * subdomain to be computed, you must nevertheless make sure that this
+ * function has access to the correct node values of @em all degrees of
+ * freedom. This is since the function needs to access DoF values on
+ * neighboring cells as well, even if they belong to a different subdomain.
*
- * The @p material_id parameter has a similar
- * meaning: if not set to its default value
- * (which is numbers::invalid_material_id),
- * it means that indicators will only be
- * computed for cells with this particular
- * material id.
+ * The @p material_id parameter has a similar meaning: if not set to its
+ * default value (which is numbers::invalid_material_id), it means that
+ * indicators will only be computed for cells with this particular material
+ * id.
*
- * The @p n_threads parameter used to
- * indicate the number of threads to be
- * used to compute the error
- * estimator. This parameter is now
- * ignored, with the number of threads
- * determined automatically. The
- * parameter is retained for
- * compatibility with old versions of the
- * library.
+ * The @p n_threads parameter used to indicate the number of threads to be
+ * used to compute the error estimator. This parameter is now ignored, with
+ * the number of threads determined automatically. The parameter is retained
+ * for compatibility with old versions of the library.
*
- * @note If the DoFHandler object
- * given as an argument to this
- * function builds on a
- * parallel::distributed::Triangulation,
- * this function skips
- * computations on all cells that
- * are not locally owned. In that
- * case, the only valid value for
- * the subdomain_id argument
- * (besides the invalid value) is
- * the subdomain id that is
- * associated with the currently
+ * @note If the DoFHandler object given as an argument to this function
+ * builds on a parallel::distributed::Triangulation, this function skips
+ * computations on all cells that are not locally owned. In that case, the
+ * only valid value for the subdomain_id argument (besides the invalid
+ * value) is the subdomain id that is associated with the currently
* processor, as reported by
* parallel::distributed::Triangulation::locally_owned_subdomain(). Even
- * though nothing is computed on
- * cells that we don't locally
- * own, the error indicator
- * vector must still have a
- * length equal to the number of
- * active cell in the mesh as
- * reported by
+ * though nothing is computed on cells that we don't locally own, the error
+ * indicator vector must still have a length equal to the number of active
+ * cell in the mesh as reported by
* parallel::distributed::Triangulation::n_locally_owned_active_cells().
*/
template <typename InputVector, class DH>
const types::material_id material_id = numbers::invalid_material_id);
/**
- * Calls the @p estimate
- * function, see above, with
+ * Calls the @p estimate function, see above, with
* <tt>mapping=MappingQ1@<dim@>()</tt>.
*/
template <typename InputVector, class DH>
const types::material_id material_id = numbers::invalid_material_id);
/**
- * Same function as above, but
- * accepts more than one solution
- * vector and returns one error
- * vector for each solution
- * vector. For the reason of
- * existence of this function,
- * see the general documentation
- * of this class.
+ * Same function as above, but accepts more than one solution vector and
+ * returns one error vector for each solution vector. For the reason of
+ * existence of this function, see the general documentation of this class.
*
- * Since we do not want to force
- * the user of this function to
- * copy around their solution
- * vectors, the vector of
- * solution vectors takes
- * pointers to the solutions,
- * rather than being a vector of
- * vectors. This makes it simpler
- * to have the solution vectors
- * somewhere in memory, rather
- * than to have them collected
- * somewhere special. (Note that
- * it is not possible to
- * construct of vector of
- * references, so we had to use a
- * vector of pointers.)
+ * Since we do not want to force the user of this function to copy around
+ * their solution vectors, the vector of solution vectors takes pointers to
+ * the solutions, rather than being a vector of vectors. This makes it
+ * simpler to have the solution vectors somewhere in memory, rather than to
+ * have them collected somewhere special. (Note that it is not possible to
+ * construct of vector of references, so we had to use a vector of
+ * pointers.)
*/
template <typename InputVector, class DH>
static void estimate (const Mapping<dim, spacedim> &mapping,
const types::material_id material_id = numbers::invalid_material_id);
/**
- * Calls the @p estimate
- * function, see above, with
+ * Calls the @p estimate function, see above, with
* <tt>mapping=MappingQ1@<dim@>()</tt>.
*/
template <typename InputVector, class DH>
/**
- * Equivalent to the set of functions
- * above, except that this one takes a
- * quadrature collection for hp finite
- * element dof handlers.
+ * Equivalent to the set of functions above, except that this one takes a
+ * quadrature collection for hp finite element dof handlers.
*/
template <typename InputVector, class DH>
static void estimate (const Mapping<dim, spacedim> &mapping,
/**
- * Equivalent to the set of functions
- * above, except that this one takes a
- * quadrature collection for hp finite
- * element dof handlers.
+ * Equivalent to the set of functions above, except that this one takes a
+ * quadrature collection for hp finite element dof handlers.
*/
template <typename InputVector, class DH>
static void estimate (const DH &dof,
/**
- * Equivalent to the set of functions
- * above, except that this one takes a
- * quadrature collection for hp finite
- * element dof handlers.
+ * Equivalent to the set of functions above, except that this one takes a
+ * quadrature collection for hp finite element dof handlers.
*/
template <typename InputVector, class DH>
static void estimate (const Mapping<dim, spacedim> &mapping,
/**
- * Equivalent to the set of functions
- * above, except that this one takes a
- * quadrature collection for hp finite
- * element dof handlers.
+ * Equivalent to the set of functions above, except that this one takes a
+ * quadrature collection for hp finite element dof handlers.
*/
template <typename InputVector, class DH>
static void estimate (const DH &dof,
{
public:
/**
- * Implementation of the error
- * estimator described above. You
- * may give a coefficient, but
- * there is a default value which
- * denotes the constant
- * coefficient with value
- * one. The coefficient function
- * may either be a scalar one, in
- * which case it is used for all
- * components of the finite
- * element, or a vector-valued
- * one with as many components as
- * there are in the finite
- * element; in the latter case,
- * each component is weighted by
- * the respective component in
- * the coefficient.
+ * Implementation of the error estimator described above. You may give a
+ * coefficient, but there is a default value which denotes the constant
+ * coefficient with value one. The coefficient function may either be a
+ * scalar one, in which case it is used for all components of the finite
+ * element, or a vector-valued one with as many components as there are in
+ * the finite element; in the latter case, each component is weighted by the
+ * respective component in the coefficient.
*
- * You might give a list of components
- * you want to evaluate, in case the
- * finite element used by the DoFHandler
- * object is vector-valued. You then have
- * to set those entries to true in the
- * bit-vector @p component_mask for which
- * the respective component is to be used
- * in the error estimator. The default is
- * to use all components, which is done
- * by either providing a bit-vector with
- * all-set entries, or an empty
- * bit-vector. All the other parameters
- * are as in the general case used for 2d
- * and higher.
+ * You might give a list of components you want to evaluate, in case the
+ * finite element used by the DoFHandler object is vector-valued. You then
+ * have to set those entries to true in the bit-vector @p component_mask for
+ * which the respective component is to be used in the error estimator. The
+ * default is to use all components, which is done by either providing a
+ * bit-vector with all-set entries, or an empty bit-vector. All the other
+ * parameters are as in the general case used for 2d and higher.
*
- * The estimator supports multithreading
- * and splits the cells to
- * <tt>multithread_info.n_default_threads</tt>
- * (default) threads. The number of
- * threads to be used in multithreaded
- * mode can be set with the last
- * parameter of the error estimator.
- * Multithreading is not presently
- * implemented for 1d, but we retain the
- * respective parameter for compatibility
- * with the function signature in the
- * general case.
+ * The estimator supports multithreading and splits the cells to
+ * <tt>multithread_info.n_default_threads</tt> (default) threads. The number
+ * of threads to be used in multithreaded mode can be set with the last
+ * parameter of the error estimator. Multithreading is not presently
+ * implemented for 1d, but we retain the respective parameter for
+ * compatibility with the function signature in the general case.
*/
template <typename InputVector, class DH>
static void estimate (const Mapping<1,spacedim> &mapping,
const types::material_id material_id = numbers::invalid_material_id);
/**
- * Calls the @p estimate
- * function, see above, with
+ * Calls the @p estimate function, see above, with
* <tt>mapping=MappingQ1<1>()</tt>.
*/
template <typename InputVector, class DH>
const types::material_id material_id = numbers::invalid_material_id);
/**
- * Same function as above, but
- * accepts more than one solution
- * vectors and returns one error
- * vector for each solution
- * vector. For the reason of
- * existence of this function,
- * see the general documentation
- * of this class.
+ * Same function as above, but accepts more than one solution vectors and
+ * returns one error vector for each solution vector. For the reason of
+ * existence of this function, see the general documentation of this class.
*
- * Since we do not want to force
- * the user of this function to
- * copy around their solution
- * vectors, the vector of
- * solution vectors takes
- * pointers to the solutions,
- * rather than being a vector of
- * vectors. This makes it simpler
- * to have the solution vectors
- * somewhere in memory, rather
- * than to have them collected
- * somewhere special. (Note that
- * it is not possible to
- * construct of vector of
- * references, so we had to use a
- * vector of pointers.)
+ * Since we do not want to force the user of this function to copy around
+ * their solution vectors, the vector of solution vectors takes pointers to
+ * the solutions, rather than being a vector of vectors. This makes it
+ * simpler to have the solution vectors somewhere in memory, rather than to
+ * have them collected somewhere special. (Note that it is not possible to
+ * construct of vector of references, so we had to use a vector of
+ * pointers.)
*/
template <typename InputVector, class DH>
static void estimate (const Mapping<1,spacedim> &mapping,
const types::material_id material_id = numbers::invalid_material_id);
/**
- * Calls the @p estimate
- * function, see above, with
+ * Calls the @p estimate function, see above, with
* <tt>mapping=MappingQ1<1>()</tt>.
*/
template <typename InputVector, class DH>
/**
- * Equivalent to the set of functions
- * above, except that this one takes a
- * quadrature collection for hp finite
- * element dof handlers.
+ * Equivalent to the set of functions above, except that this one takes a
+ * quadrature collection for hp finite element dof handlers.
*/
template <typename InputVector, class DH>
static void estimate (const Mapping<1,spacedim> &mapping,
/**
- * Equivalent to the set of functions
- * above, except that this one takes a
- * quadrature collection for hp finite
- * element dof handlers.
+ * Equivalent to the set of functions above, except that this one takes a
+ * quadrature collection for hp finite element dof handlers.
*/
template <typename InputVector, class DH>
static void estimate (const DH &dof,
/**
- * Equivalent to the set of functions
- * above, except that this one takes a
- * quadrature collection for hp finite
- * element dof handlers.
+ * Equivalent to the set of functions above, except that this one takes a
+ * quadrature collection for hp finite element dof handlers.
*/
template <typename InputVector, class DH>
static void estimate (const Mapping<1,spacedim> &mapping,
/**
- * Equivalent to the set of functions
- * above, except that this one takes a
- * quadrature collection for hp finite
- * element dof handlers.
+ * Equivalent to the set of functions above, except that this one takes a
+ * quadrature collection for hp finite element dof handlers.
*/
template <typename InputVector, class DH>
static void estimate (const DH &dof,
/**
- * Compute the constraints that
- * correspond to boundary conditions of
- * the form $\vec n \cdot \vec u=0$,
- * i.e. no normal flux if $\vec u$ is a
- * vector-valued quantity. These
- * conditions have exactly the form
- * handled by the ConstraintMatrix class,
- * so instead of creating a map between
- * boundary degrees of freedom and
- * corresponding value, we here create a
- * list of constraints that are written
- * into a ConstraintMatrix. This object
- * may already have some content, for
- * example from hanging node constraints,
- * that remains untouched. These
- * constraints have to be applied to the
- * linear system like any other such
- * constraints, i.e. you have to condense
- * the linear system with the constraints
- * before solving, and you have to
- * distribute the solution vector
- * afterwards.
- *
- * The use of this function is
- * explained in more detail in
- * step-31. It
- * doesn't make much sense in 1d,
- * so the function throws an
- * exception in that case.
- *
- * The second argument of this
- * function denotes the first
- * vector component in the finite
- * element that corresponds to
- * the vector function that you
- * want to constrain. For
- * example, if we were solving a
- * Stokes equation in 2d and the
- * finite element had components
- * $(u,v,p)$, then @p
- * first_vector_component would
- * be zero. On the other hand, if
- * we solved the Maxwell
- * equations in 3d and the finite
- * element has components
- * $(E_x,E_y,E_z,B_x,B_y,B_z)$
- * and we want the boundary
- * condition $\vec n\cdot \vec
- * B=0$, then @p
- * first_vector_component would
- * be 3. Vectors are implicitly
- * assumed to have exactly
- * <code>dim</code> components
- * that are ordered in the same
- * way as we usually order the
- * coordinate directions,
- * i.e. $x$-, $y$-, and finally
- * $z$-component. The function
- * assumes, but can't check, that
- * the vector components in the
- * range
- * <code>[first_vector_component,first_vector_component+dim)</code>
- * come from the same base finite
- * element. For example, in the
- * Stokes example above, it would
- * not make sense to use a
- * <code>FESystem@<dim@>(FE_Q@<dim@>(2),
- * 1, FE_Q@<dim@>(1), dim)</code>
- * (note that the first velocity
- * vector component is a $Q_2$
- * element, whereas all the other
- * ones are $Q_1$ elements) as
- * there would be points on the
- * boundary where the
- * $x$-velocity is defined but no
- * corresponding $y$- or
- * $z$-velocities.
- *
- * The third argument denotes the set of
- * boundary indicators on which the
- * boundary condition is to be
- * enforced. Note that, as explained
- * below, this is one of the few
- * functions where it makes a difference
- * where we call the function multiple
- * times with only one boundary
- * indicator, or whether we call the
- * function onces with the whole set of
- * boundary indicators at once.
- *
- * The mapping argument is used to
- * compute the boundary points where the function
- * needs to request the normal vector $\vec n$
- * from the boundary description.
- *
- * @note When combining adaptively
- * refined meshes with hanging node
- * constraints and boundary conditions
- * like from the current function within
- * one ConstraintMatrix object, the
- * hanging node constraints should always
- * be set first, and then the boundary
- * conditions since boundary conditions
- * are not set in the second operation on
- * degrees of freedom that are already
- * constrained. This makes sure that the
- * discretization remains conforming as
- * is needed. See the discussion on
- * conflicting constraints in the module
- * on @ref constraints .
+ * Compute the constraints that correspond to boundary conditions of the
+ * form $\vec n \cdot \vec u=0$, i.e. no normal flux if $\vec u$ is a
+ * vector-valued quantity. These conditions have exactly the form handled by
+ * the ConstraintMatrix class, so instead of creating a map between boundary
+ * degrees of freedom and corresponding value, we here create a list of
+ * constraints that are written into a ConstraintMatrix. This object may
+ * already have some content, for example from hanging node constraints,
+ * that remains untouched. These constraints have to be applied to the
+ * linear system like any other such constraints, i.e. you have to condense
+ * the linear system with the constraints before solving, and you have to
+ * distribute the solution vector afterwards.
+ *
+ * The use of this function is explained in more detail in step-31. It
+ * doesn't make much sense in 1d, so the function throws an exception in
+ * that case.
+ *
+ * The second argument of this function denotes the first vector component
+ * in the finite element that corresponds to the vector function that you
+ * want to constrain. For example, if we were solving a Stokes equation in
+ * 2d and the finite element had components $(u,v,p)$, then @p
+ * first_vector_component would be zero. On the other hand, if we solved the
+ * Maxwell equations in 3d and the finite element has components
+ * $(E_x,E_y,E_z,B_x,B_y,B_z)$ and we want the boundary condition $\vec
+ * n\cdot \vec B=0$, then @p first_vector_component would be 3. Vectors are
+ * implicitly assumed to have exactly <code>dim</code> components that are
+ * ordered in the same way as we usually order the coordinate directions,
+ * i.e. $x$-, $y$-, and finally $z$-component. The function assumes, but
+ * can't check, that the vector components in the range
+ * <code>[first_vector_component,first_vector_component+dim)</code> come
+ * from the same base finite element. For example, in the Stokes example
+ * above, it would not make sense to use a
+ * <code>FESystem@<dim@>(FE_Q@<dim@>(2), 1, FE_Q@<dim@>(1), dim)</code>
+ * (note that the first velocity vector component is a $Q_2$ element,
+ * whereas all the other ones are $Q_1$ elements) as there would be points
+ * on the boundary where the $x$-velocity is defined but no corresponding
+ * $y$- or $z$-velocities.
+ *
+ * The third argument denotes the set of boundary indicators on which the
+ * boundary condition is to be enforced. Note that, as explained below, this
+ * is one of the few functions where it makes a difference where we call the
+ * function multiple times with only one boundary indicator, or whether we
+ * call the function onces with the whole set of boundary indicators at
+ * once.
+ *
+ * The mapping argument is used to compute the boundary points where the
+ * function needs to request the normal vector $\vec n$ from the boundary
+ * description.
+ *
+ * @note When combining adaptively refined meshes with hanging node
+ * constraints and boundary conditions like from the current function within
+ * one ConstraintMatrix object, the hanging node constraints should always
+ * be set first, and then the boundary conditions since boundary conditions
+ * are not set in the second operation on degrees of freedom that are
+ * already constrained. This makes sure that the discretization remains
+ * conforming as is needed. See the discussion on conflicting constraints in
+ * the module on @ref constraints .
*
*
* <h4>Computing constraints in 2d</h4>
*
- * Computing these constraints requires
- * some smarts. The main question
- * revolves around the question what the
- * normal vector is. Consider the
- * following situation:
- * <p ALIGN="center">
- * @image html no_normal_flux_1.png
+ * Computing these constraints requires some smarts. The main question
+ * revolves around the question what the normal vector is. Consider the
+ * following situation: <p ALIGN="center"> @image html no_normal_flux_1.png
* </p>
*
- * Here, we have two cells that use a
- * bilinear mapping
- * (i.e. MappingQ1). Consequently, for
- * each of the cells, the normal vector
- * is perpendicular to the straight
- * edge. If the two edges at the top and
- * right are meant to approximate a
- * curved boundary (as indicated by the
- * dashed line), then neither of the two
- * computed normal vectors are equal to
- * the exact normal vector (though they
- * approximate it as the mesh is refined
- * further). What is worse, if we
- * constrain $\vec n \cdot \vec u=0$ at
- * the common vertex with the normal
- * vector from both cells, then we
- * constrain the vector $\vec u$ with
- * respect to two linearly independent
- * vectors; consequently, the constraint
- * would be $\vec u=0$ at this point
- * (i.e. <i>all</i> components of the
- * vector), which is not what we wanted.
- *
- * To deal with this situation, the
- * algorithm works in the following way:
- * at each point where we want to
- * constrain $\vec u$, we first collect
- * all normal vectors that adjacent cells
- * might compute at this point. We then
- * do not constrain $\vec n \cdot \vec
- * u=0$ for <i>each</i> of these normal
- * vectors but only for the
- * <i>average</i> of the normal
- * vectors. In the example above, we
- * therefore record only a single
- * constraint $\vec n \cdot \vec {\bar
- * u}=0$, where $\vec {\bar u}$ is the
- * average of the two indicated normal
- * vectors.
- *
- * Unfortunately, this is not quite
- * enough. Consider the situation here:
+ * Here, we have two cells that use a bilinear mapping
+ * (i.e. MappingQ1). Consequently, for each of the cells, the normal vector
+ * is perpendicular to the straight edge. If the two edges at the top and
+ * right are meant to approximate a curved boundary (as indicated by the
+ * dashed line), then neither of the two computed normal vectors are equal
+ * to the exact normal vector (though they approximate it as the mesh is
+ * refined further). What is worse, if we constrain $\vec n \cdot \vec u=0$
+ * at the common vertex with the normal vector from both cells, then we
+ * constrain the vector $\vec u$ with respect to two linearly independent
+ * vectors; consequently, the constraint would be $\vec u=0$ at this point
+ * (i.e. <i>all</i> components of the vector), which is not what we wanted.
+ *
+ * To deal with this situation, the algorithm works in the following way: at
+ * each point where we want to constrain $\vec u$, we first collect all
+ * normal vectors that adjacent cells might compute at this point. We then
+ * do not constrain $\vec n \cdot \vec u=0$ for <i>each</i> of these normal
+ * vectors but only for the <i>average</i> of the normal vectors. In the
+ * example above, we therefore record only a single constraint $\vec n \cdot
+ * \vec {\bar u}=0$, where $\vec {\bar u}$ is the average of the two
+ * indicated normal vectors.
+ *
+ * Unfortunately, this is not quite enough. Consider the situation here:
*
* <p ALIGN="center">
* @image html no_normal_flux_2.png
* </p>
*
- * If again the top and right edges
- * approximate a curved boundary, and the
- * left boundary a separate boundary (for
- * example straight) so that the exact
- * boundary has indeed a corner at the
- * top left vertex, then the above
- * construction would not work: here, we
- * indeed want the constraint that $\vec
- * u$ at this point (because the normal
- * velocities with respect to both the
- * left normal as well as the top normal
- * vector should be zero), not that the
- * velocity in the direction of the
- * average normal vector is zero.
- *
- * Consequently, we use the following
- * heuristic to determine whether all
- * normal vectors computed at one point
- * are to be averaged: if two normal
- * vectors for the same point are
- * computed on <i>different</i> cells,
- * then they are to be averaged. This
- * covers the first example above. If
- * they are computed from the same cell,
- * then the fact that they are different
- * is considered indication that they
- * come from different parts of the
- * boundary that might be joined by a
- * real corner, and must not be averaged.
- *
- * There is one problem with this
- * scheme. If, for example, the same
- * domain we have considered above, is
- * discretized with the following mesh,
- * then we get into trouble:
+ * If again the top and right edges approximate a curved boundary, and the
+ * left boundary a separate boundary (for example straight) so that the
+ * exact boundary has indeed a corner at the top left vertex, then the above
+ * construction would not work: here, we indeed want the constraint that
+ * $\vec u$ at this point (because the normal velocities with respect to
+ * both the left normal as well as the top normal vector should be zero),
+ * not that the velocity in the direction of the average normal vector is
+ * zero.
+ *
+ * Consequently, we use the following heuristic to determine whether all
+ * normal vectors computed at one point are to be averaged: if two normal
+ * vectors for the same point are computed on <i>different</i> cells, then
+ * they are to be averaged. This covers the first example above. If they are
+ * computed from the same cell, then the fact that they are different is
+ * considered indication that they come from different parts of the boundary
+ * that might be joined by a real corner, and must not be averaged.
+ *
+ * There is one problem with this scheme. If, for example, the same domain
+ * we have considered above, is discretized with the following mesh, then we
+ * get into trouble:
*
* <p ALIGN="center">
* @image html no_normal_flux_3.png
* </p>
*
- * Here, the algorithm assumes that the
- * boundary does not have a corner at the
- * point where faces $F1$ and $F2$ join
- * because at that point there are two
- * different normal vectors computed from
- * different cells. If you intend for
- * there to be a corner of the exact
- * boundary at this point, the only way
- * to deal with this is to assign the two
- * parts of the boundary different
- * boundary indicators and call this
- * function twice, once for each boundary
- * indicators; doing so will yield only
- * one normal vector at this point per
- * invocation (because we consider only
- * one boundary part at a time), with the
- * result that the normal vectors will
- * not be averaged.
+ * Here, the algorithm assumes that the boundary does not have a corner at
+ * the point where faces $F1$ and $F2$ join because at that point there are
+ * two different normal vectors computed from different cells. If you intend
+ * for there to be a corner of the exact boundary at this point, the only
+ * way to deal with this is to assign the two parts of the boundary
+ * different boundary indicators and call this function twice, once for each
+ * boundary indicators; doing so will yield only one normal vector at this
+ * point per invocation (because we consider only one boundary part at a
+ * time), with the result that the normal vectors will not be averaged. This
+ * situation also needs to be taken into account when using this function
+ * around reentrant corners on Cartesian meshes. If no-normal-flux boundary
+ * conditions are to be enforced on non-Cartesian meshes around reentrant
+ * corners, one may even get cycles in the constraints as one will in
+ * general constrain different components from the two sides. In that case,
+ * set a no-slip constraint on the reentrant vertex first.
*
*
* <h4>Computing constraints in 3d</h4>
*
- * The situation is more
- * complicated in 3d. Consider
- * the following case where we
- * want to compute the
- * constraints at the marked
- * vertex:
+ * The situation is more complicated in 3d. Consider the following case
+ * where we want to compute the constraints at the marked vertex:
*
* <p ALIGN="center">
* @image html no_normal_flux_4.png
* </p>
*
- * Here, we get four different
- * normal vectors, one from each
- * of the four faces that meet at
- * the vertex. Even though they
- * may form a complete set of
- * vectors, it is not our intent
- * to constrain all components of
- * the vector field at this
- * point. Rather, we would like
- * to still allow tangential
- * flow, where the term
- * "tangential" has to be
- * suitably defined.
- *
- * In a case like this, the
- * algorithm proceeds as follows:
- * for each cell that has
- * computed two tangential
- * vectors at this point, we
- * compute the unconstrained
- * direction as the outer product
- * of the two tangential vectors
- * (if necessary multiplied by
- * minus one). We then average
- * these tangential
- * vectors. Finally, we compute
- * constraints for the two
- * directions perpendicular to
- * this averaged tangential
- * direction.
- *
- * There are cases where one cell
- * contributes two tangential
- * directions and another one
- * only one; for example, this
- * would happen if both top and
- * front faces of the left cell
- * belong to the boundary
- * selected whereas only the top
- * face of the right cell belongs
- * to it. This case is not
- * currently implemented.
+ * Here, we get four different normal vectors, one from each of the four
+ * faces that meet at the vertex. Even though they may form a complete set
+ * of vectors, it is not our intent to constrain all components of the
+ * vector field at this point. Rather, we would like to still allow
+ * tangential flow, where the term "tangential" has to be suitably defined.
+ *
+ * In a case like this, the algorithm proceeds as follows: for each cell
+ * that has computed two tangential vectors at this point, we compute the
+ * unconstrained direction as the outer product of the two tangential
+ * vectors (if necessary multiplied by minus one). We then average these
+ * tangential vectors. Finally, we compute constraints for the two
+ * directions perpendicular to this averaged tangential direction.
+ *
+ * There are cases where one cell contributes two tangential directions and
+ * another one only one; for example, this would happen if both top and
+ * front faces of the left cell belong to the boundary selected whereas only
+ * the top face of the right cell belongs to it. This case is not currently
+ * implemented.
*
*
* <h4>Results</h4>
*
- * Because it makes for good
- * pictures, here are two images
- * of vector fields on a circle
- * and on a sphere to which the
- * constraints computed by this
+ * Because it makes for good pictures, here are two images of vector fields
+ * on a circle and on a sphere to which the constraints computed by this
* function have been applied:
*
* <p ALIGN="center">
* @image html no_normal_flux_6.png
* </p>
*
- * The vectors fields are not
- * physically reasonable but the
- * tangentiality constraint is
- * clearly enforced. The fact
- * that the vector fields are
- * zero at some points on the
- * boundary is an artifact of the
- * way it is created, it is not
- * constrained to be zero at
- * these points.
+ * The vectors fields are not physically reasonable but the tangentiality
+ * constraint is clearly enforced. The fact that the vector fields are zero
+ * at some points on the boundary is an artifact of the way it is created,
+ * it is not constrained to be zero at these points.
*
* @ingroup constraints
*
ConstraintMatrix &constraints,
const Mapping<dim, spacedim> &mapping = StaticMappingQ1<dim>::mapping);
+ /**
+ * Compute the constraints that correspond to boundary conditions of the
+ * form $\vec n \times \vec u=0$, i.e. flow normal to the boundary if $\vec
+ * u$ is a vector-valued quantity. This function constrains exactly those
+ * vector-valued components that are left unconstrained by
+ * compute_no_normal_flux_constraints, and leaves the one component
+ * unconstrained that is constrained by compute_no_normal_flux_constraints.
+ */
+ template <int dim, template <int, int> class DH, int spacedim>
+ void
+ compute_normal_flux_constraints (const DH<dim,spacedim> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<dim, spacedim> &mapping = StaticMappingQ1<dim>::mapping);
+
//@}
/**
* Exception
*/
DeclException0 (ExcNonInterpolatingFE);
-
- /**
- * Exception
- */
- DeclException0 (ExcNoComponentSelected);
}
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
+#include <deal.II/base/std_cxx1x/array.h>
#include <numeric>
#include <algorithm>
#include <vector>
-// separate implementation for 1D because otherwise we get linker errors since
-// FEFaceValues<1> is not compiled
- template <>
- void
- create_boundary_right_hand_side (const Mapping<1,1> &,
- const DoFHandler<1,1> &,
- const Quadrature<0> &,
- const Function<1> &,
- Vector<double> &,
- const std::set<types::boundary_id> &)
- {
- Assert (false, ExcImpossibleInDim(1));
- }
-
-
-
- template <>
- void
- create_boundary_right_hand_side (const Mapping<1,2> &,
- const DoFHandler<1,2> &,
- const Quadrature<0> &,
- const Function<2> &,
- Vector<double> &,
- const std::set<types::boundary_id> &)
- {
- Assert (false, ExcImpossibleInDim(1));
- }
-
-
-
template <int dim, int spacedim>
void
create_boundary_right_hand_side (const Mapping<dim, spacedim> &mapping,
-// separate implementation for 1D because otherwise we get linker errors since
-// hp::FEFaceValues<1> is not compiled
- template <>
- void
- create_boundary_right_hand_side (const hp::MappingCollection<1,1> &,
- const hp::DoFHandler<1,1> &,
- const hp::QCollection<0> &,
- const Function<1> &,
- Vector<double> &,
- const std::set<types::boundary_id> &)
- {
- Assert (false, ExcImpossibleInDim(1));
- }
-
-
-
- template <>
- void
- create_boundary_right_hand_side (const hp::MappingCollection<1,2> &,
- const hp::DoFHandler<1,2> &,
- const hp::QCollection<0> &,
- const Function<2> &,
- Vector<double> &,
- const std::set<types::boundary_id> &)
- {
- Assert (false, ExcImpossibleInDim(1));
- }
-
-
-
template <int dim, int spacedim>
void
create_boundary_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
boundary_function.n_components));
Assert (component_mask.n_selected_components(fe.n_components()) > 0,
- ExcNoComponentSelected());
+ ComponentMask::ExcNoComponentSelected());
// now set the value of
// the vertex degree of
}
}
- // Create the system
- // matrix by
- // multiplying the
- // assembling matrix
- // with its transposed
- // and the right
- // hand side vector
- // by mutliplying
- // the assembling
- // matrix with the
- // assembling vector.
- // Invert the system
- // matrix.
+ // Create the system matrix by multiplying the assembling matrix
+ // with its transposed and the right hand side vector by mutliplying
+ // the assembling matrix with the assembling vector. Invert the
+ // system matrix.
assembling_matrix.mTmult (cell_matrix, assembling_matrix);
cell_matrix_inv.invert (cell_matrix);
assembling_matrix.vmult (cell_rhs, assembling_vector);
}
}
- // Now we do the
- // same as above
- // with the vertical
- // shape functions
- // instead of the
- // horizontal ones.
+ // Now we do the same as above with the vertical shape functions
+ // instead of the horizontal ones.
for (unsigned int q_point = 0;
q_point < fe_values.n_quadrature_points; ++q_point)
{
ConstraintMatrix &constraints,
const Mapping<dim> &mapping)
{
- // Projection-based interpolation
- // is performed in two (in 2D)
- // respectively three (in 3D)
- // steps. First the tangential
- // component of the function is
- // interpolated on each edge. This
- // gives the values for the degrees
- // of freedom corresponding to the
- // edge shape functions. Now we are
- // done for 2D, but in 3D we possibly
- // have also degrees of freedom, which
- // are located in the interior of
- // the faces. Therefore we compute
- // the residual of the function
- // describing the boundary values
- // and the interpolated part, which
- // we have computed in the last
- // step. On the faces there are
- // two kinds of shape functions,
- // the horizontal and the vertical
- // ones. Thus we have to solve two
- // linear systems of equations of
- // size <tt>degree * (degree +
- // 1)<tt> to obtain the values for
- // the corresponding degrees of
- // freedom.
+ // Projection-based interpolation is performed in two (in 2D) respectively
+ // three (in 3D) steps. First the tangential component of the function is
+ // interpolated on each edge. This gives the values for the degrees of
+ // freedom corresponding to the edge shape functions. Now we are done for
+ // 2D, but in 3D we possibly have also degrees of freedom, which are
+ // located in the interior of the faces. Therefore we compute the residual
+ // of the function describing the boundary values and the interpolated
+ // part, which we have computed in the last step. On the faces there are
+ // two kinds of shape functions, the horizontal and the vertical
+ // ones. Thus we have to solve two linear systems of equations of size
+ // <tt>degree * (degree + 1)<tt> to obtain the values for the
+ // corresponding degrees of freedom.
const unsigned int superdegree = dof_handler.get_fe ().degree;
const QGauss<dim - 1> reference_face_quadrature (2 * superdegree);
const unsigned int dofs_per_face = dof_handler.get_fe ().dofs_per_face;
for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
if (cell->face (face)->boundary_indicator () == boundary_component)
{
- // if the FE is a
- // FE_Nothing object
- // there is no work to
- // do
+ // if the FE is a FE_Nothing object there is no work to do
if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
return;
- // This is only
- // implemented, if the
- // FE is a Nedelec
- // element. If the FE is
- // a FESystem we cannot
- // check this.
+ // This is only implemented, if the FE is a Nedelec
+ // element. If the FE is a FESystem we cannot check this.
if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
{
typedef FiniteElement<dim> FEL;
for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
if (cell->face (face)->boundary_indicator () == boundary_component)
{
- // if the FE is a
- // FE_Nothing object
- // there is no work to
- // do
+ // if the FE is a FE_Nothing object there is no work to do
if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
return;
- // This is only
- // implemented, if the
- // FE is a Nedelec
- // element. If the FE is
- // a FESystem we cannot
- // check this.
+ // This is only implemented, if the FE is a Nedelec
+ // element. If the FE is a FESystem we cannot check this.
if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
{
typedef FiniteElement<dim> FEL;
first_vector_component,
dof_values, dofs_processed);
- // If there are higher
- // order shape
- // functions, there is
- // still some work
- // left.
+ // If there are higher order shape functions, there is still
+ // some work left.
if (degree > 0)
internals
::compute_face_projection_curl_conforming (cell, face, fe_face_values,
namespace internals
{
- // This function computes the
- // projection of the boundary
- // function on the boundary
- // in 2d.
+ // This function computes the projection of the boundary function on the
+ // boundary in 2d.
template <typename cell_iterator>
void
compute_face_projection_div_conforming (const cell_iterator &cell,
const std::vector<DerivativeForm<1,2,2> > &jacobians,
ConstraintMatrix &constraints)
{
- // Compute the intergral over
- // the product of the normal
- // components of the boundary
- // function times the normal
- // components of the shape
- // functions supported on the
- // boundary.
+ // Compute the intergral over the product of the normal components of
+ // the boundary function times the normal components of the shape
+ // functions supported on the boundary.
const FEValuesExtractors::Vector vec (first_vector_component);
const FiniteElement<2> &fe = cell->get_fe ();
const std::vector<Point<2> > &normals = fe_values.get_normal_vectors ();
values (fe_values.n_quadrature_points, Vector<double> (2));
Vector<double> dof_values (fe.dofs_per_face);
- // Get the values of the
- // boundary function at the
- // quadrature points.
+ // Get the values of the boundary function at the quadrature points.
{
const std::vector<Point<2> > &
quadrature_points = fe_values.get_quadrature_points ();
cell->face (face)->get_dof_indices (face_dof_indices, cell->active_fe_index ());
- // Copy the computed values
- // in the ConstraintMatrix only,
- // if the degree of freedom is
- // not already constrained.
+ // Copy the computed values in the ConstraintMatrix only, if the degree
+ // of freedom is not already constrained.
for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
if (!(constraints.is_constrained (face_dof_indices[i])))
{
}
}
- // dummy implementation of above
- // function for all other
- // dimensions
+ // dummy implementation of above function for all other dimensions
template<int dim, typename cell_iterator>
void
compute_face_projection_div_conforming (const cell_iterator &,
Assert (false, ExcNotImplemented ());
}
- // This function computes the
- // projection of the boundary
- // function on the boundary
- // in 3d.
+ // This function computes the projection of the boundary function on the
+ // boundary in 3d.
template<typename cell_iterator>
void
compute_face_projection_div_conforming (const cell_iterator &cell,
std::vector<double> &dof_values,
std::vector<types::global_dof_index> &projected_dofs)
{
- // Compute the intergral over
- // the product of the normal
- // components of the boundary
- // function times the normal
- // components of the shape
- // functions supported on the
- // boundary.
+ // Compute the intergral over the product of the normal components of
+ // the boundary function times the normal components of the shape
+ // functions supported on the boundary.
const FEValuesExtractors::Vector vec (first_vector_component);
const FiniteElement<3> &fe = cell->get_fe ();
const std::vector<Point<3> > &normals = fe_values.get_normal_vectors ();
+ namespace
+ {
+ template <int dim>
+ struct PointComparator
+ {
+ bool operator ()(const std_cxx1x::array<types::global_dof_index,dim> &p1,
+ const std_cxx1x::array<types::global_dof_index,dim> &p2)
+ {
+ for (unsigned int d=0; d<dim; ++d)
+ if (p1[d] < p2[d])
+ return true;
+ return false;
+ }
+ };
+ }
+
+
+
+ template <int dim, template <int, int> class DH, int spacedim>
+ void
+ compute_normal_flux_constraints (const DH<dim,spacedim>&dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<dim, spacedim> &mapping)
+ {
+ ConstraintMatrix no_normal_flux_constraints(constraints.get_local_lines());
+ compute_no_normal_flux_constraints (dof_handler,
+ first_vector_component,
+ boundary_ids,
+ no_normal_flux_constraints,
+ mapping);
+
+ // Extract a list that collects all vector components that belong to the
+ // same node (scalar basis function). When creating that list, we use an
+ // array of dim components that stores the global degree of freedom.
+ std::set<std_cxx1x::array<types::global_dof_index,dim>, PointComparator<dim> > vector_dofs;
+ std::vector<types::global_dof_index> face_dofs;
+
+ std::vector<std_cxx1x::array<types::global_dof_index,dim> > cell_vector_dofs;
+ for (typename DH<dim,spacedim>::active_cell_iterator cell =
+ dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
+ if (!cell->is_artificial())
+ for (unsigned int face_no=0; face_no < GeometryInfo<dim>::faces_per_cell;
+ ++face_no)
+ if (boundary_ids.find(cell->face(face_no)->boundary_indicator())
+ != boundary_ids.end())
+ {
+ const FiniteElement<dim> &fe = cell->get_fe();
+ typename DH<dim,spacedim>::face_iterator face=cell->face(face_no);
+
+ // get the indices of the dofs on this cell...
+ face_dofs.resize (fe.dofs_per_face);
+ face->get_dof_indices (face_dofs, cell->active_fe_index());
+
+ unsigned int n_scalar_indices = 0;
+ cell_vector_dofs.resize(fe.dofs_per_face);
+ for (unsigned int i=0; i<fe.dofs_per_face; ++i)
+ if (fe.face_system_to_component_index(i).first >= first_vector_component &&
+ fe.face_system_to_component_index(i).first < first_vector_component + dim)
+ {
+ n_scalar_indices =
+ std::max(n_scalar_indices,
+ fe.face_system_to_component_index(i).second+1);
+ cell_vector_dofs[fe.face_system_to_component_index(i).second]
+ [fe.face_system_to_component_index(i).first-first_vector_component]
+ = face_dofs[i];
+ }
+
+ // now we identified the vector indices on the cell, so next
+ // insert them into the set (it would be expensive to directly
+ // insert incomplete points into the set)
+ for (unsigned int i=0; i<n_scalar_indices; ++i)
+ vector_dofs.insert(cell_vector_dofs[i]);
+ }
+
+ // iterate over the list of all vector components we found and see if we
+ // can find constrained ones
+ unsigned int n_total_constraints_found = 0;
+ for (typename std::set<std_cxx1x::array<unsigned int,dim>,PointComparator<dim> >::
+ const_iterator it=vector_dofs.begin(); it!=vector_dofs.end(); ++it)
+ {
+ unsigned int n_constraints = 0;
+ bool is_constrained[dim];
+ for (unsigned int d=0; d<dim; ++d)
+ if (no_normal_flux_constraints.is_constrained((*it)[d]))
+ {
+ is_constrained[d] = true;
+ ++n_constraints;
+ ++n_total_constraints_found;
+ }
+ else
+ is_constrained[d] = false;
+ if (n_constraints > 0)
+ {
+ // if more than one no-flux constraint is present, we need to
+ // constrain all vector degrees of freedom (we are in a corner
+ // where several faces meet and to get a continuous FE solution we
+ // need to set all conditions to zero).
+ if (n_constraints > 1)
+ {
+ for (unsigned int d=0; d<dim; ++d)
+ constraints.add_line((*it)[d]);
+ continue;
+ }
+
+ // ok, this is a no-flux constraint, so get the index of the dof
+ // that is currently constrained and make it unconstrained. The
+ // constraint indices will get the normal that contain the other
+ // indices.
+ Tensor<1,dim> normal;
+ unsigned constrained_index = -1;
+ for (unsigned int d=0; d<dim; ++d)
+ if (is_constrained[d])
+ {
+ constrained_index = d;
+ normal[d] = 1.;
+ }
+ AssertIndexRange(constrained_index, dim);
+ const std::vector<std::pair<unsigned int, double> >* constrained
+ = no_normal_flux_constraints.get_constraint_entries((*it)[constrained_index]);
+ // find components to which this index is constrained to
+ Assert(constrained != 0, ExcInternalError());
+ Assert(constrained->size() < dim, ExcInternalError());
+ for (unsigned int c=0; c<constrained->size(); ++c)
+ {
+ int index = -1;
+ for (unsigned int d=0; d<dim; ++d)
+ if ((*constrained)[c].first == (*it)[d])
+ index = d;
+ Assert (index != -1, ExcInternalError());
+ normal[index] = (*constrained)[c].second;
+ }
+ for (unsigned int d=0; d<dim; ++d)
+ {
+ if (is_constrained[d])
+ continue;
+ const unsigned int new_index = (*it)[d];
+ if (!constraints.is_constrained(new_index))
+ {
+ constraints.add_line(new_index);
+ if (std::abs(normal[d]) > 1e-13)
+ constraints.add_entry(new_index, (*it)[constrained_index],
+ -normal[d]);
+ }
+ }
+ }
+ }
+ AssertDimension(n_total_constraints_found,
+ no_normal_flux_constraints.n_constraints());
+ }
+
+
+
namespace internal
{
+ template <int dim, int spacedim>
+ struct IDScratchData
+ {
+ IDScratchData (const dealii::hp::MappingCollection<dim,spacedim> &mapping,
+ const dealii::hp::FECollection<dim,spacedim> &fe,
+ const dealii::hp::QCollection<dim> &q,
+ const UpdateFlags update_flags);
+
+ IDScratchData (const IDScratchData &data);
+
+ void resize_vectors (const unsigned int n_q_points,
+ const unsigned int n_components);
+
+ std::vector<dealii::Vector<double> > function_values;
+ std::vector<std::vector<Tensor<1,spacedim> > > function_grads;
+ std::vector<double> weight_values;
+ std::vector<dealii::Vector<double> > weight_vectors;
+
+ std::vector<dealii::Vector<double> > psi_values;
+ std::vector<std::vector<Tensor<1,spacedim> > > psi_grads;
+ std::vector<double> psi_scalar;
+
+ std::vector<double> tmp_values;
+ std::vector<Tensor<1,spacedim> > tmp_gradients;
+
+ dealii::hp::FEValues<dim,spacedim> x_fe_values;
+ };
+
+
+ template <int dim, int spacedim>
+ IDScratchData<dim,spacedim>
+ ::IDScratchData(const dealii::hp::MappingCollection<dim,spacedim> &mapping,
+ const dealii::hp::FECollection<dim,spacedim> &fe,
+ const dealii::hp::QCollection<dim> &q,
+ const UpdateFlags update_flags)
+ :
+ x_fe_values(mapping, fe, q, update_flags)
+ {}
+
+ template <int dim, int spacedim>
+ IDScratchData<dim,spacedim>::IDScratchData (const IDScratchData &data)
+ :
+ x_fe_values(data.x_fe_values.get_mapping_collection(),
+ data.x_fe_values.get_fe_collection(),
+ data.x_fe_values.get_quadrature_collection(),
+ data.x_fe_values.get_update_flags())
+ {}
+
+ template <int dim, int spacedim>
+ void
+ IDScratchData<dim,spacedim>::resize_vectors (const unsigned int n_q_points,
+ const unsigned int n_components)
+ {
+ function_values.resize (n_q_points,
+ dealii::Vector<double>(n_components));
+ function_grads.resize (n_q_points,
+ std::vector<Tensor<1,spacedim> >(n_components));
+
+ weight_values.resize (n_q_points);
+ weight_vectors.resize (n_q_points,
+ dealii::Vector<double>(n_components));
+
+ psi_values.resize (n_q_points,
+ dealii::Vector<double>(n_components));
+ psi_grads.resize (n_q_points,
+ std::vector<Tensor<1,spacedim> >(n_components));
+ psi_scalar.resize (n_q_points);
+
+ tmp_values.resize (n_q_points);
+ tmp_gradients.resize (n_q_points);
+ }
+
+
+ // avoid compiling inner function for many vector types when we always
+ // really do the same thing by putting the main work into this helper
+ // function
+ template <int dim, int spacedim>
+ double
+ integrate_difference_inner (const Function<spacedim> &exact_solution,
+ const NormType &norm,
+ const Function<spacedim> *weight,
+ const UpdateFlags update_flags,
+ const double exponent,
+ const unsigned int n_components,
+ IDScratchData<dim,spacedim> &data)
+ {
+ const bool fe_is_system = (n_components != 1);
+ const dealii::FEValues<dim, spacedim> &fe_values = data.x_fe_values.get_present_fe_values ();
+ const unsigned int n_q_points = fe_values.n_quadrature_points;
+
+ if (weight!=0)
+ {
+ if (weight->n_components>1)
+ weight->vector_value_list (fe_values.get_quadrature_points(),
+ data.weight_vectors);
+ else
+ {
+ weight->value_list (fe_values.get_quadrature_points(),
+ data.weight_values);
+ for (unsigned int k=0; k<n_q_points; ++k)
+ data.weight_vectors[k] = data.weight_values[k];
+ }
+ }
+ else
+ {
+ for (unsigned int k=0; k<n_q_points; ++k)
+ data.weight_vectors[k] = 1.;
+ }
+
+
+ if (update_flags & update_values)
+ {
+ // first compute the exact solution (vectors) at the quadrature
+ // points try to do this as efficient as possible by avoiding a
+ // second virtual function call in case the function really has only
+ // one component
+ if (fe_is_system)
+ exact_solution.vector_value_list (fe_values.get_quadrature_points(),
+ data.psi_values);
+ else
+ {
+ exact_solution.value_list (fe_values.get_quadrature_points(),
+ data.tmp_values);
+ for (unsigned int i=0; i<n_q_points; ++i)
+ data.psi_values[i](0) = data.tmp_values[i];
+ }
+
+ // then subtract finite element fe_function
+ for (unsigned int q=0; q<n_q_points; ++q)
+ data.psi_values[q] -= data.function_values[q];
+ }
+
+ // Do the same for gradients, if required
+ if (update_flags & update_gradients)
+ {
+ // try to be a little clever to avoid recursive virtual function
+ // calls when calling gradient_list for functions that are really
+ // scalar functions
+ if (fe_is_system)
+ exact_solution.vector_gradient_list (fe_values.get_quadrature_points(),
+ data.psi_grads);
+ else
+ {
+ exact_solution.gradient_list (fe_values.get_quadrature_points(),
+ data.tmp_gradients);
+ for (unsigned int i=0; i<n_q_points; ++i)
+ data.psi_grads[i][0] = data.tmp_gradients[i];
+ }
+
+ // then subtract finite element function_grads. We need to be
+ // careful in the codimension one case, since there we only have
+ // tangential gradients in the finite element function, not the full
+ // gradient. This is taken care of, by subtracting the normal
+ // component of the gradient from the exact function.
+ if (update_flags & update_normal_vectors)
+ for (unsigned int k=0; k<n_components; ++k)
+ for (unsigned int q=0; q<n_q_points; ++q)
+ data.psi_grads[q][k] -= (data.function_grads[q][k] +
+ (data.psi_grads[q][k]* // (f.n) n
+ fe_values.normal_vector(q))*
+ fe_values.normal_vector(q));
+ else
+ for (unsigned int k=0; k<n_components; ++k)
+ for (unsigned int q=0; q<n_q_points; ++q)
+ data.psi_grads[q][k] -= data.function_grads[q][k];
+ }
+
+ double diff = 0;
+ switch (norm)
+ {
+ case mean:
+ // Compute values in quadrature points and integrate
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ double sum = 0;
+ for (unsigned int k=0; k<n_components; ++k)
+ sum += data.psi_values[q](k) * data.weight_vectors[q](k);
+ diff += sum * fe_values.JxW(q);
+ }
+ break;
+
+ case Lp_norm:
+ case L1_norm:
+ case W1p_norm:
+ // Compute values in quadrature points and integrate
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ double sum = 0;
+ for (unsigned int k=0; k<n_components; ++k)
+ sum += std::pow(data.psi_values[q](k)*data.psi_values[q](k),
+ exponent/2.) * data.weight_vectors[q](k);
+ diff += sum * fe_values.JxW(q);
+ }
+
+ // Compute the root only, if no derivative values are added later
+ if (!(update_flags & update_gradients))
+ diff = std::pow(diff, 1./exponent);
+ break;
+
+ case L2_norm:
+ case H1_norm:
+ // Compute values in quadrature points and integrate
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ double sum = 0;
+ for (unsigned int k=0; k<n_components; ++k)
+ sum += data.psi_values[q](k) * data.psi_values[q](k) *
+ data.weight_vectors[q](k);
+ diff += sum * fe_values.JxW(q);
+ }
+ // Compute the root only, if no derivative values are added later
+ if (norm == L2_norm)
+ diff=std::sqrt(diff);
+ break;
+
+ case Linfty_norm:
+ case W1infty_norm:
+ for (unsigned int q=0; q<n_q_points; ++q)
+ for (unsigned int k=0; k<n_components; ++k)
+ diff = std::max (diff, std::abs(data.psi_values[q](k)*
+ data.weight_vectors[q](k)));
+ break;
+
+ case H1_seminorm:
+ case W1p_seminorm:
+ case W1infty_seminorm:
+ break;
+
+ default:
+ Assert (false, ExcNotImplemented());
+ break;
+ }
+
+ switch (norm)
+ {
+ case W1p_seminorm:
+ case W1p_norm:
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ double sum = 0;
+ for (unsigned int k=0; k<n_components; ++k)
+ sum += std::pow(data.psi_grads[q][k]*data.psi_grads[q][k],
+ exponent/2.) * data.weight_vectors[q](k);
+ diff += sum * fe_values.JxW(q);
+ }
+ diff = std::pow(diff, 1./exponent);
+ break;
+
+ case H1_seminorm:
+ case H1_norm:
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ double sum = 0;
+ for (unsigned int k=0; k<n_components; ++k)
+ sum += (data.psi_grads[q][k] * data.psi_grads[q][k]) *
+ data.weight_vectors[q](k);
+ diff += sum * fe_values.JxW(q);
+ }
+ diff = std::sqrt(diff);
+ break;
+
+ case W1infty_seminorm:
+ case W1infty_norm:
+ {
+ double t = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ for (unsigned int k=0; k<n_components; ++k)
+ for (unsigned int d=0; d<dim; ++d)
+ t = std::max(t, std::abs(data.psi_grads[q][k][d]) *
+ data.weight_vectors[q](k));
+
+ // then add seminorm to norm if that had previously been computed
+ diff += t;
+ }
+ break;
+ default:
+ break;
+ }
+
+ // append result of this cell to the end of the vector
+ Assert (numbers::is_finite(diff), ExcNumberNotFinite());
+ return diff;
+ }
+
+
+
template <int dim, class InVector, class OutVector, class DH, int spacedim>
static
void
- do_integrate_difference (const dealii::hp::MappingCollection<dim,spacedim> &mapping,
+ do_integrate_difference (const dealii::hp::MappingCollection<dim,spacedim> &mapping,
const DH &dof,
const InVector &fe_function,
const Function<spacedim> &exact_solution,
const Function<spacedim> *weight,
const double exponent_1)
{
- // we mark the "exponent" parameter
- // to this function "const" since
- // it is strictly incoming, but we
- // need to set it to something
- // different later on, if
- // necessary, so have a read-write
- // version of it:
+ // we mark the "exponent" parameter to this function "const" since it is
+ // strictly incoming, but we need to set it to something different later
+ // on, if necessary, so have a read-write version of it:
double exponent = exponent_1;
const unsigned int n_components = dof.get_fe().n_components();
}
dealii::hp::FECollection<dim,spacedim> fe_collection (dof.get_fe());
- dealii::hp::FEValues<dim,spacedim> x_fe_values(mapping, fe_collection, q, update_flags);
-
- const unsigned int max_n_q_points = q.max_n_quadrature_points ();
-
- std::vector< dealii::Vector<double> >
- function_values (max_n_q_points, dealii::Vector<double>(n_components));
- std::vector<std::vector<Tensor<1,spacedim> > >
- function_grads (max_n_q_points, std::vector<Tensor<1,spacedim> >(n_components));
-
- std::vector<double>
- weight_values (max_n_q_points);
- std::vector<dealii::Vector<double> >
- weight_vectors (max_n_q_points, dealii::Vector<double>(n_components));
-
- std::vector<dealii::Vector<double> >
- psi_values (max_n_q_points, dealii::Vector<double>(n_components));
- std::vector<std::vector<Tensor<1,spacedim> > >
- psi_grads (max_n_q_points, std::vector<Tensor<1,spacedim> >(n_components));
- std::vector<double>
- psi_scalar (max_n_q_points);
-
- // tmp vector when we use the
- // Function<spacedim> functions for
- // scalar functions
- std::vector<double> tmp_values (max_n_q_points);
- std::vector<Tensor<1,spacedim> > tmp_gradients (max_n_q_points);
+ IDScratchData<dim,spacedim> data(mapping, fe_collection, q, update_flags);
// loop over all cells
typename DH::active_cell_iterator cell = dof.begin_active(),
for (unsigned int index=0; cell != endc; ++cell, ++index)
if (cell->is_locally_owned())
{
- double diff=0;
// initialize for this cell
- x_fe_values.reinit (cell);
+ data.x_fe_values.reinit (cell);
- const dealii::FEValues<dim, spacedim> &fe_values = x_fe_values.get_present_fe_values ();
+ const dealii::FEValues<dim, spacedim> &fe_values = data.x_fe_values.get_present_fe_values ();
const unsigned int n_q_points = fe_values.n_quadrature_points;
-
- // resize all out scratch
- // arrays to the number of
- // quadrature points we use
- // for the present cell
- function_values.resize (n_q_points,
- dealii::Vector<double>(n_components));
- function_grads.resize (n_q_points,
- std::vector<Tensor<1,spacedim> >(n_components));
-
- weight_values.resize (n_q_points);
- weight_vectors.resize (n_q_points,
- dealii::Vector<double>(n_components));
-
- psi_values.resize (n_q_points,
- dealii::Vector<double>(n_components));
- psi_grads.resize (n_q_points,
- std::vector<Tensor<1,spacedim> >(n_components));
- psi_scalar.resize (n_q_points);
-
- tmp_values.resize (n_q_points);
- tmp_gradients.resize (n_q_points);
-
- if (weight!=0)
- {
- if (weight->n_components>1)
- weight->vector_value_list (fe_values.get_quadrature_points(),
- weight_vectors);
- else
- {
- weight->value_list (fe_values.get_quadrature_points(),
- weight_values);
- for (unsigned int k=0; k<n_q_points; ++k)
- weight_vectors[k] = weight_values[k];
- }
- }
- else
- {
- for (unsigned int k=0; k<n_q_points; ++k)
- weight_vectors[k] = 1.;
- }
-
+ data.resize_vectors (n_q_points, n_components);
if (update_flags & update_values)
- {
- // first compute the exact solution
- // (vectors) at the quadrature points
- // try to do this as efficient as
- // possible by avoiding a second
- // virtual function call in case
- // the function really has only
- // one component
- if (fe_is_system)
- exact_solution.vector_value_list (fe_values.get_quadrature_points(),
- psi_values);
- else
- {
- exact_solution.value_list (fe_values.get_quadrature_points(),
- tmp_values);
- for (unsigned int i=0; i<n_q_points; ++i)
- psi_values[i](0) = tmp_values[i];
- }
-
- // then subtract finite element
- // fe_function
- fe_values.get_function_values (fe_function, function_values);
- for (unsigned int q=0; q<n_q_points; ++q)
- psi_values[q] -= function_values[q];
- }
-
- // Do the same for gradients, if required
+ fe_values.get_function_values (fe_function, data.function_values);
if (update_flags & update_gradients)
- {
- // try to be a little clever
- // to avoid recursive virtual
- // function calls when calling
- // gradient_list for functions
- // that are really scalar
- // functions
- if (fe_is_system)
- exact_solution.vector_gradient_list (fe_values.get_quadrature_points(),
- psi_grads);
- else
- {
- exact_solution.gradient_list (fe_values.get_quadrature_points(),
- tmp_gradients);
- for (unsigned int i=0; i<n_q_points; ++i)
- psi_grads[i][0] = tmp_gradients[i];
- }
-
- // then subtract finite element
- // function_grads. We
- // need to be careful
- // in the codimension
- // one case, since
- // there we only have
- // tangential gradients
- // in the finite
- // element function,
- // not the full
- // gradient. This is
- // taken care of, by
- // subtracting the
- // normal component of
- // the gradient from
- // the exact function.
- fe_values.get_function_grads (fe_function, function_grads);
- if (update_flags & update_normal_vectors)
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- psi_grads[q][k] -= (function_grads[q][k] +
- (psi_grads[q][k]* // (f.n) n
- fe_values.normal_vector(q))*
- fe_values.normal_vector(q));
- else
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- psi_grads[q][k] -= function_grads[q][k];
- }
-
- switch (norm)
- {
- case mean:
- std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
- // Compute values in
- // quadrature points
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- psi_scalar[q] += psi_values[q](k)
- * weight_vectors[q](k);
-
- // Integrate
- diff = std::inner_product (psi_scalar.begin(), psi_scalar.end(),
- fe_values.get_JxW_values().begin(),
- 0.0);
- break;
- case Lp_norm:
- case L1_norm:
- case W1p_norm:
- std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
- // Compute values in
- // quadrature points
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- psi_scalar[q] += std::pow(psi_values[q](k)*psi_values[q](k),
- exponent/2.)
- * weight_vectors[q](k);
-
- // Integrate
- diff = std::inner_product (psi_scalar.begin(), psi_scalar.end(),
- fe_values.get_JxW_values().begin(),
- 0.0);
- // Compute the root only,
- // if no derivative
- // values are added later
- if (!(update_flags & update_gradients))
- diff = std::pow(diff, 1./exponent);
- break;
- case L2_norm:
- case H1_norm:
- std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
- // Compute values in
- // quadrature points
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- psi_scalar[q] += psi_values[q](k)*psi_values[q](k)
- * weight_vectors[q](k);
-
- // Integrate
- diff = std::inner_product (psi_scalar.begin(), psi_scalar.end(),
- fe_values.get_JxW_values().begin(),
- 0.0);
- // Compute the root only,
- // if no derivative
- // values are added later
- if (norm == L2_norm)
- diff=std::sqrt(diff);
- break;
- case Linfty_norm:
- case W1infty_norm:
- std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- {
- double newval = std::fabs(psi_values[q](k))
- * weight_vectors[q](k);
- if (psi_scalar[q]<newval)
- psi_scalar[q] = newval;
- }
- // Maximum on one cell
- diff = *std::max_element (psi_scalar.begin(), psi_scalar.end());
- break;
- case H1_seminorm:
- case W1p_seminorm:
- case W1infty_seminorm:
- break;
- default:
- Assert (false, ExcNotImplemented());
- break;
- }
+ fe_values.get_function_grads (fe_function, data.function_grads);
- switch (norm)
- {
- case W1p_seminorm:
- case W1p_norm:
- std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- psi_scalar[q] += std::pow(psi_grads[q][k] * psi_grads[q][k],
- exponent/2.)
- * weight_vectors[q](k);
-
- diff += std::inner_product (psi_scalar.begin(), psi_scalar.end(),
- fe_values.get_JxW_values().begin(),
- 0.0);
- diff = std::pow(diff, 1./exponent);
- break;
- case H1_seminorm:
- case H1_norm:
- // take square of integrand
- std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- psi_scalar[q] += (psi_grads[q][k] * psi_grads[q][k])
- * weight_vectors[q](k);
-
- // add seminorm to L_2 norm or
- // to zero
- diff += std::inner_product (psi_scalar.begin(), psi_scalar.end(),
- fe_values.get_JxW_values().begin(),
- 0.0);
- diff = std::sqrt(diff);
- break;
-
- case W1infty_seminorm:
- case W1infty_norm:
- std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
- for (unsigned int k=0; k<n_components; ++k)
- for (unsigned int q=0; q<n_q_points; ++q)
- {
- double t = 0.;
- for (unsigned int d=0; d<dim; ++d)
- t = std::max(t,std::fabs(psi_grads[q][k][d])
- * weight_vectors[q](k));
-
- psi_scalar[q] = std::max(psi_scalar[q],t);
- }
-
- // compute seminorm
- {
- double t = 0;
- for (unsigned int i=0; i<psi_scalar.size(); ++i)
- t = std::max (t, psi_scalar[i]);
-
- // then add seminorm to norm if that had previously been
- // computed
- diff += t;
- }
- break;
- default:
- break;
- }
- // append result of this cell
- // to the end of the vector
- Assert (numbers::is_finite(diff), ExcNumberNotFinite());
- difference(index) = diff;
+ difference(index) =
+ integrate_difference_inner (exact_solution, norm, weight,
+ update_flags, exponent,
+ n_components, data);
}
else
- // the cell is a ghost cell
- // or is artificial. write
- // a zero into the
- // corresponding value of
- // the returned vector
+ // the cell is a ghost cell or is artificial. write a zero into the
+ // corresponding value of the returned vector
difference(index) = 0;
}
const double exponent)
{
internal
- ::do_integrate_difference(hp::StaticMappingQ1<dim>::mapping_collection,
+ ::do_integrate_difference(hp::StaticMappingQ1<dim,spacedim>::mapping_collection,
dof, fe_function, exact_solution,
difference, q,
norm, weight, exponent);
}
// Error out if we have not constrained anything. Note that in this
// case the vector v is always nonempty.
- Assert (n == 0 || counter > 0, ExcNoComponentSelected());
+ Assert (n == 0 || counter > 0, ComponentMask::ExcNoComponentSelected());
s /= counter;
)
TARGET_LINK_LIBRARIES(${DEAL_II_BASE_NAME}${DEAL_II_${build}_SUFFIX}
- ${DEAL_II_EXTERNAL_LIBRARIES}
${DEAL_II_EXTERNAL_LIBRARIES_${build}}
+ ${DEAL_II_EXTERNAL_LIBRARIES}
)
INSTALL(TARGETS ${DEAL_II_BASE_NAME}${DEAL_II_${build}_SUFFIX}
const int polar_angle,
const unsigned int line_thickness,
const bool margin,
- const bool draw_colorbar) :
- height_vector(height_vector),
- azimuth_angle(azimuth_angle),
- polar_angle(polar_angle),
- line_thickness(line_thickness),
- margin(margin),
- draw_colorbar(draw_colorbar)
+ const bool draw_colorbar)
+ :
+ height(4000),
+ width(0),
+ height_vector(height_vector),
+ azimuth_angle(azimuth_angle),
+ polar_angle(polar_angle),
+ line_thickness(line_thickness),
+ margin(margin),
+ draw_colorbar(draw_colorbar)
{}
// do not allow volume rendering
AssertThrow (dim==2, ExcNotImplemented());
- const unsigned int height = 4000;
- unsigned int width;
+ const unsigned int height = flags.height;
+ unsigned int width = flags.width;
// margin around the plotted area
unsigned int margin_in_percent = 0;
}
}
}
-
+
// write the svg file
- width = static_cast<unsigned int>(.5 + height * (x_dimension_perspective / y_dimension_perspective));
+ if (width==0)
+ width = static_cast<unsigned int>(.5 + height * (x_dimension_perspective / y_dimension_perspective));
unsigned int additional_width = 0;
if (flags.draw_colorbar) additional_width = static_cast<unsigned int>(.5 + height * .3); // additional width for colorbar
MPI_Info info;
MPI_Info_create(&info);
MPI_File fh;
- MPI_File_open(MPI_COMM_WORLD, const_cast<char *>(filename),
+ MPI_File_open(comm, const_cast<char *>(filename),
MPI_MODE_CREATE | MPI_MODE_WRONLY, info, &fh);
MPI_File_set_size(fh, 0); // delete the file contents
// this barrier is necessary, because otherwise others might already
List::List (const PatternBase &p,
const unsigned int min_elements,
- const unsigned int max_elements)
+ const unsigned int max_elements,
+ const std::string &separator)
:
pattern (p.clone()),
min_elements (min_elements),
- max_elements (max_elements)
+ max_elements (max_elements),
+ separator (separator)
{
Assert (min_elements <= max_elements,
ExcInvalidRange (min_elements, max_elements));
+ Assert (separator.size() > 0,
+ ExcMessage ("The separator must have a non-zero length."));
}
{
std::string tmp = test_string_list;
std::vector<std::string> split_list;
- split_list.reserve (std::count (tmp.begin(), tmp.end(), ',')+1);
// first split the input list
while (tmp.length() != 0)
std::string name;
name = tmp;
- if (name.find(",") != std::string::npos)
+ if (name.find(separator) != std::string::npos)
{
- name.erase (name.find(","), std::string::npos);
- tmp.erase (0, tmp.find(",")+1);
+ name.erase (name.find(separator), std::string::npos);
+ tmp.erase (0, tmp.find(separator)+separator.size());
}
else
tmp = "";
name.erase (name.length()-1, 1);
split_list.push_back (name);
- };
+ }
if ((split_list.size() < min_elements) ||
(split_list.size() > max_elements))
description << description_init
<< " list of <" << pattern->description() << ">"
<< " of length " << min_elements << "..." << max_elements
- << " (inclusive)"
- << "]";
+ << " (inclusive)";
+ if (separator != ",")
+ description << " separated by <" << separator << ">";
+ description << "]";
return description.str();
}
PatternBase *
List::clone () const
{
- return new List(*pattern, min_elements, max_elements);
+ return new List(*pattern, min_elements, max_elements, separator);
}
List::memory_consumption () const
{
return (sizeof(*this) +
- MemoryConsumption::memory_consumption(*pattern));
+ MemoryConsumption::memory_consumption(*pattern) +
+ MemoryConsumption::memory_consumption(separator));
}
if (!(is >> max_elements))
return new List(*base_pattern, min_elements);
- return new List(*base_pattern, min_elements, max_elements);
+ is.ignore(strlen(" separated by <"));
+ std::string separator;
+ if (!is)
+ std::getline(is, separator, '>');
+ else
+ separator = ",";
+
+ return new List(*base_pattern, min_elements, max_elements, separator);
}
else
return 0;
Map::Map (const PatternBase &p_key,
const PatternBase &p_value,
const unsigned int min_elements,
- const unsigned int max_elements)
+ const unsigned int max_elements,
+ const std::string &separator)
:
key_pattern (p_key.clone()),
value_pattern (p_value.clone()),
min_elements (min_elements),
- max_elements (max_elements)
+ max_elements (max_elements),
+ separator (separator)
{
Assert (min_elements <= max_elements,
ExcInvalidRange (min_elements, max_elements));
+ Assert (separator.size() > 0,
+ ExcMessage ("The separator must have a non-zero length."));
+ Assert (separator != ":",
+ ExcMessage ("The separator can not be a colon ':' sicne that "
+ "is the separator between the two elements of <key:value> pairs"));
}
{
std::string tmp = test_string_list;
std::vector<std::string> split_list;
- split_list.reserve (std::count (tmp.begin(), tmp.end(), ',')+1);
// first split the input list at comma sites
while (tmp.length() != 0)
std::string map_entry;
map_entry = tmp;
- if (map_entry.find(",") != std::string::npos)
+ if (map_entry.find(separator) != std::string::npos)
{
- map_entry.erase (map_entry.find(","), std::string::npos);
- tmp.erase (0, tmp.find(",")+1);
+ map_entry.erase (map_entry.find(separator), std::string::npos);
+ tmp.erase (0, tmp.find(separator)+separator.size());
}
else
tmp = "";
map_entry.erase (map_entry.length()-1, 1);
split_list.push_back (map_entry);
- };
+ }
if ((split_list.size() < min_elements) ||
(split_list.size() > max_elements))
<< key_pattern->description() << ":"
<< value_pattern->description() << ">"
<< " of length " << min_elements << "..." << max_elements
- << " (inclusive)"
- << "]";
+ << " (inclusive)";
+ if (separator != ",")
+ description << " separated by <" << separator << ">";
+ description << "]";
return description.str();
}
PatternBase *
Map::clone () const
{
- return new Map(*key_pattern, *value_pattern, min_elements, max_elements);
+ return new Map(*key_pattern, *value_pattern,
+ min_elements, max_elements,
+ separator);
}
{
return (sizeof(*this) +
MemoryConsumption::memory_consumption (*key_pattern) +
- MemoryConsumption::memory_consumption (*value_pattern));
+ MemoryConsumption::memory_consumption (*value_pattern) +
+ MemoryConsumption::memory_consumption (separator));
}
if (!(is >> max_elements))
return new Map(*key_pattern, *value_pattern, min_elements);
- return new Map(*key_pattern, *value_pattern, min_elements, max_elements);
+ is.ignore(strlen(" separated by <"));
+ std::string separator;
+ if (!is)
+ std::getline(is, separator, '>');
+ else
+ separator = ",";
+
+ return new Map(*key_pattern, *value_pattern,
+ min_elements, max_elements,
+ separator);
}
else
return 0;
-bool ParameterHandler::read_input (std::istream &input)
+bool ParameterHandler::read_input (std::istream &input,
+ const std::string &filename)
{
AssertThrow (input, ExcIO());
{
++lineno;
getline (input, line);
- if (!scan_line (line, lineno))
- status = false;
+ status &= scan_line (line, filename, lineno);
}
return status;
std::ifstream input (openname.c_str());
AssertThrow(input, ExcIO());
- return read_input (input);
+ return read_input (input, filename);
}
catch (const PathSearch::ExcFileNotFound &)
{
bool ParameterHandler::read_input_from_string (const char *s)
{
- // if empty std::string then exit
- // with success
- if ((s == 0) || ((*s) == 0)) return true;
-
- std::string line;
- std::string input (s);
- int lineno=0;
-
- // if necessary append a newline char
- // to make all lines equal
- if (input[input.length()-1] != '\n')
- input += '\n';
-
- bool status = true;
- while (input.size() != 0)
- {
- // get one line from Input (=s)
- line.assign (input, 0, input.find('\n'));
- // delete this part including
- // the backspace
- input.erase (0, input.find('\n')+1);
- ++lineno;
-
- if (!scan_line (line, lineno))
- status = false;
- }
-
- return status;
+ // create an istringstream representation and pass it off
+ // to the other functions doing this work
+ std::istringstream in (s);
+ return read_input (in, "input string");
}
entries->put (get_current_full_path(entry) + path_separator +
"pattern_description",
patterns.back()->description());
+
+ // as documented, do the default value checking at the very end
+ AssertThrow (pattern.match (default_value),
+ ExcValueDoesNotMatchPattern (default_value, pattern.description()));
}
bool
-ParameterHandler::scan_line (std::string line,
- const unsigned int lineno)
+ParameterHandler::scan_line (std::string line,
+ const std::string &input_filename,
+ const unsigned int lineno)
{
// if there is a comment, delete it
if (line.find('#') != std::string::npos)
line.erase (line.find(" "), 1);
// now every existing whitespace
// should be exactly one ' ';
- // if at end or beginning: delete
- if ((line.length() != 0) && (std::isspace (line[0]))) line.erase (0, 1);
+ // if at beginning: delete
+ if ((line.length() != 0) && (std::isspace (line[0])))
+ line.erase (0, 1);
// if line is now empty: leave
- if (line.length() == 0) return true;
+ if (line.length() == 0)
+ return true;
+ // also delete spaces at the end
if (std::isspace (line[line.length()-1]))
line.erase (line.size()-1, 1);
// check whether subsection exists
if (!entries->get_child_optional (get_current_full_path(subsection)))
{
- std::cerr << "Line " << lineno
- << ": There is no such subsection to be entered: "
+ std::cerr << "Line <" << lineno
+ << "> of file <" << input_filename
+ << ">: There is no such subsection to be entered: "
<< demangle(get_current_full_path(subsection)) << std::endl;
for (unsigned int i=0; i<subsection_path.size(); ++i)
std::cerr << std::setw(i*2+4) << " "
{
if (subsection_path.size() == 0)
{
- std::cerr << "Line " << lineno
- << ": There is no subsection to leave here!" << std::endl;
+ std::cerr << "Line <" << lineno
+ << "> of file <" << input_filename
+ << ">: There is no subsection to leave here!" << std::endl;
return false;
}
else
= entries->get<unsigned int> (get_current_full_path(entry_name) + path_separator + "pattern");
if (!patterns[pattern_index]->match(entry_value))
{
- std::cerr << "Line " << lineno << ":" << std::endl
+ std::cerr << "Line <" << lineno
+ << "> of file <" << input_filename
+ << ">:" << std::endl
<< " The entry value" << std::endl
<< " " << entry_value << std::endl
<< " for the entry named" << std::endl
}
else
{
- std::cerr << "Line " << lineno
- << ": No such entry was declared:" << std::endl
+ std::cerr << "Line <" << lineno
+ << "> of file <" << input_filename
+ << ">: No such entry was declared:" << std::endl
<< " " << entry_name << std::endl
<< " <Present subsection:" << std::endl;
for (unsigned int i=0; i<subsection_path.size(); ++i)
}
}
+ // an include statement?
+ if ((line.find ("INCLUDE ") == 0) ||
+ (line.find ("include ") == 0))
+ {
+ // erase "set" statement and eliminate
+ // spaces around the '='
+ line.erase (0, 7);
+ while ((line.size() > 0) && (line[0] == ' '))
+ line.erase (0, 1);
+
+ // the remainder must then be a filename
+ if (line.size() == 0)
+ {
+ std::cerr << "Line <" << lineno
+ << "> of file <" << input_filename
+ << "> is an include statement but does not name a file!"
+ << std::endl;
+
+ return false;
+ }
+
+ std::ifstream input (line.c_str());
+ if (!input)
+ {
+ std::cerr << "Line <" << lineno
+ << "> of file <" << input_filename
+ << "> is an include statement but the file <"
+ << line << "> could not be opened!"
+ << std::endl;
+
+ return false;
+ }
+ else
+ return read_input (input);
+ }
+
// this line matched nothing known
- std::cerr << "Line " << lineno
- << ": This line matched nothing known ('set' or 'subsection' missing!?):" << std::endl
+ std::cerr << "Line <" << lineno
+ << "> of file <" << input_filename
+ << ">: This line matched nothing known ('set' or 'subsection' missing!?):" << std::endl
<< " " << line << std::endl;
return false;
}
void
Partitioner::set_ghost_indices (const IndexSet &ghost_indices_in)
{
- // Set ghost indices from input. To be sure
- // that no entries from the locally owned
- // range are present, subtract the locally
- // owned indices in any case.
+ // Set ghost indices from input. To be sure that no entries from the
+ // locally owned range are present, subtract the locally owned indices
+ // in any case.
Assert (ghost_indices_in.n_elements() == 0 ||
ghost_indices_in.size() == locally_owned_range_data.size(),
ExcDimensionMismatch (ghost_indices_in.size(),
ghost_indices_data.compress();
n_ghost_indices_data = ghost_indices_data.n_elements();
- // In the rest of this function, we determine
- // the point-to-point communication pattern of
- // the partitioner. We make up a list with
- // both the processors the ghost indices
- // actually belong to, and the indices that
- // are locally held but ghost indices of other
- // processors. This allows then to import and
- // export data very easily.
-
- // find out the end index for each processor
- // and communicate it (this implies the start
- // index for the next processor)
+ // In the rest of this function, we determine the point-to-point
+ // communication pattern of the partitioner. We make up a list with both
+ // the processors the ghost indices actually belong to, and the indices
+ // that are locally held but ghost indices of other processors. This
+ // allows then to import and export data very easily.
+
+ // find out the end index for each processor and communicate it (this
+ // implies the start index for the next processor)
#ifdef DEAL_II_WITH_MPI
if (n_procs < 2)
{
MPI_BYTE, communicator);
first_index[n_procs] = global_size;
- // fix case when there are some processors
- // without any locally owned indices: then
- // there might be a zero in some entries
+ // fix case when there are some processors without any locally owned
+ // indices: then there might be a zero in some entries
if (global_size > 0)
{
unsigned int first_proc_with_nonzero_dofs = 0;
if (first_index[i] == 0)
first_index[i] = first_index[i-1];
- // correct if our processor has a wrong local
- // range
+ // correct if our processor has a wrong local range
if (first_index[my_pid] != local_range_data.first)
{
Assert(local_range_data.first == local_range_data.second,
}
}
- // Allocate memory for data that will be
- // exported
+ // Allocate memory for data that will be exported
std::vector<types::global_dof_index> expanded_ghost_indices (n_ghost_indices_data);
unsigned int n_ghost_targets = 0;
if (n_ghost_indices_data > 0)
{
- // Create first a vector of ghost_targets from
- // the list of ghost indices and then push
- // back new values. When we are done, copy the
- // data to that field of the partitioner. This
- // way, the variable ghost_targets will have
- // exactly the size we need, whereas the
- // vector filled with push_back might actually
- // be too long.
+ // Create first a vector of ghost_targets from the list of ghost
+ // indices and then push back new values. When we are done, copy the
+ // data to that field of the partitioner. This way, the variable
+ // ghost_targets will have exactly the size we need, whereas the
+ // vector filled with push_back might actually be too long.
unsigned int current_proc = 0;
ghost_indices_data.fill_index_vector (expanded_ghost_indices);
unsigned int current_index = expanded_ghost_indices[0];
n_ghost_indices_data - ghost_targets_temp[n_ghost_targets-1].second;
ghost_targets_data = ghost_targets_temp;
}
- // find the processes that want to import to
- // me
+ // find the processes that want to import to me
{
std::vector<int> send_buffer (n_procs, 0);
std::vector<int> receive_buffer (n_procs, 0);
import_targets_data = import_targets_temp;
}
- // send and receive indices for import
- // data. non-blocking receives and blocking
- // sends
+ // send and receive indices for import data. non-blocking receives and
+ // blocking sends
std::vector<types::global_dof_index> expanded_import_indices (n_import_indices_data);
{
unsigned int current_index_start = 0;
MPI_Waitall (import_requests.size(), &import_requests[0],
MPI_STATUSES_IGNORE);
- // transform import indices to local index
- // space and compress contiguous indices in
- // form of ranges
+ // transform import indices to local index space and compress
+ // contiguous indices in form of ranges
{
types::global_dof_index last_index = numbers::invalid_dof_index-1;
std::vector<std::pair<types::global_dof_index,types::global_dof_index> > compressed_import_indices;
SET(_src
block_info.cc
dof_accessor.cc
+ dof_accessor_get.cc
+ dof_accessor_set.cc
dof_faces.cc
dof_handler.cc
dof_handler_policy.cc
dof_objects.cc
dof_renumbering.cc
dof_tools.cc
+ dof_tools_constraints.cc
+ dof_tools_sparsity.cc
number_cache.cc
)
SET(_inst
block_info.inst.in
dof_accessor.inst.in
+ dof_accessor_get.inst.in
+ dof_accessor_set.inst.in
dof_handler.inst.in
dof_handler_policy.inst.in
dof_objects.inst.in
dof_renumbering.inst.in
dof_tools.inst.in
+ dof_tools_constraints.inst.in
+ dof_tools_sparsity.inst.in
)
DEAL_II_ADD_LIBRARY(obj_dofs OBJECT ${_src} ${_header} ${_inst})
//
// ---------------------------------------------------------------------
-#include <deal.II/lac/vector.h>
-#include <deal.II/lac/block_vector.h>
-#include <deal.II/lac/parallel_vector.h>
-#include <deal.II/lac/parallel_block_vector.h>
-#include <deal.II/lac/petsc_vector.h>
-#include <deal.II/lac/petsc_block_vector.h>
-#include <deal.II/lac/trilinos_vector.h>
-#include <deal.II/lac/trilinos_block_vector.h>
-#include <deal.II/lac/sparse_matrix.h>
-
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_levels.h>
-template <class DH, bool lda>
-template <class InputVector, typename number>
-void
-DoFCellAccessor<DH,lda>::
-get_interpolated_dof_values (const InputVector &values,
- Vector<number> &interpolated_values) const
-{
- const FiniteElement<dim,spacedim> &fe = this->get_fe();
- const unsigned int dofs_per_cell = fe.dofs_per_cell;
-
- Assert (this->dof_handler != 0,
- typename BaseClass::ExcInvalidObject());
- Assert (&fe != 0,
- typename BaseClass::ExcInvalidObject());
- Assert (interpolated_values.size() == dofs_per_cell,
- typename BaseClass::ExcVectorDoesNotMatch());
- Assert (values.size() == this->dof_handler->n_dofs(),
- typename BaseClass::ExcVectorDoesNotMatch());
-
- if (!this->has_children())
- // if this cell has no children: simply
- // return the exact values on this cell
- this->get_dof_values (values, interpolated_values);
- else
- // otherwise clobber them from the children
- {
- Vector<number> tmp1(dofs_per_cell);
- Vector<number> tmp2(dofs_per_cell);
-
- interpolated_values = 0;
-
- // later on we will have to
- // push the values interpolated
- // from the child to the mother
- // cell into the output
- // vector. unfortunately, there
- // are two types of elements:
- // ones where you add up the
- // contributions from the
- // different child cells, and
- // ones where you overwrite.
- //
- // an example for the first is
- // piecewise constant (and
- // discontinuous) elements,
- // where we build the value on
- // the coarse cell by averaging
- // the values from the cell
- // (i.e. by adding up a
- // fraction of the values of
- // their values)
- //
- // an example for the latter
- // are the usual continuous
- // elements. the value on a
- // vertex of a coarse cell must
- // there be the same,
- // irrespective of the adjacent
- // cell we are presently on. so
- // we always overwrite. in
- // fact, we must, since we
- // cannot know in advance how
- // many neighbors there will
- // be, so there is no way to
- // compute the average with
- // fixed factors
- //
- // so we have to find out to
- // which type this element
- // belongs. the difficulty is:
- // the finite element may be a
- // composed one, so we can only
- // hope to do this for each
- // shape function
- // individually. in fact, there
- // are even weird finite
- // elements (for example the
- // Raviart-Thomas element)
- // which have shape functions
- // that are additive (interior
- // ones) and others that are
- // overwriting (face degrees of
- // freedom that need to be
- // continuous across the
- // face). to avoid checking
- // this over and over again, we
- // do this once now and cache
- // the results
- std::vector<bool> restriction_is_additive (dofs_per_cell);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- restriction_is_additive[i] = fe.restriction_is_additive(i);
-
- for (unsigned int child=0; child<this->n_children(); ++child)
- {
- // get the values from the present
- // child, if necessary by
- // interpolation itself
- this->child(child)->get_interpolated_dof_values (values,
- tmp1);
- // interpolate these to the mother
- // cell
- fe.get_restriction_matrix(child, this->refinement_case()).vmult (tmp2, tmp1);
-
- // and add up or set them
- // in the output vector
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- if (restriction_is_additive[i])
- interpolated_values(i) += tmp2(i);
- else if (tmp2(i) != number())
- interpolated_values(i) = tmp2(i);
- }
- }
-}
-
-
-
-template <class DH, bool lda>
-template <class OutputVector, typename number>
-void
-DoFCellAccessor<DH,lda>::
-set_dof_values_by_interpolation (const Vector<number> &local_values,
- OutputVector &values) const
-{
- const unsigned int dofs_per_cell = this->get_fe().dofs_per_cell;
-
- Assert (this->dof_handler != 0,
- typename BaseClass::ExcInvalidObject());
- Assert (&this->get_fe() != 0,
- typename BaseClass::ExcInvalidObject());
- Assert (local_values.size() == dofs_per_cell,
- typename BaseClass::ExcVectorDoesNotMatch());
- Assert (values.size() == this->dof_handler->n_dofs(),
- typename BaseClass::ExcVectorDoesNotMatch());
-
- if (!this->has_children())
- // if this cell has no children: simply
- // set the values on this cell
- this->set_dof_values (local_values, values);
- else
- // otherwise distribute them to the children
- {
- Vector<number> tmp(dofs_per_cell);
-
- for (unsigned int child=0; child<this->n_children(); ++child)
- {
- Assert (this->child(child)->get_fe().dofs_per_cell == dofs_per_cell,
- ExcNotImplemented());
-
- // prolong the given data
- // to the present
- // cell. FullMatrix only
- // wants us to call vmult
- // if the matrix size is
- // actually non-zero, so
- // check that case
- if (tmp.size() > 0)
- {
- this->get_fe().get_prolongation_matrix(child, this->refinement_case())
- .vmult (tmp, local_values);
-
- this->child(child)->set_dof_values_by_interpolation (tmp, values);
- }
- }
- }
-}
-
-
-
// --------------------------------------------------------------------------
// explicit instantiations
#include "dof_accessor.inst"
#endif
}
-
-for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
- {
- template
- void
- DoFCellAccessor<DoFHandler<deal_II_dimension>, lda>::get_interpolated_dof_values
- (const VEC&, Vector<SCALAR>&) const;
- template
- void
- DoFCellAccessor<DoFHandler<deal_II_dimension>, lda>::set_dof_values_by_interpolation
- (const Vector<SCALAR>&, VEC&) const;
-
-#if deal_II_dimension != 3
-
- template
- void
- DoFCellAccessor<DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::get_interpolated_dof_values
- (const VEC&, Vector<SCALAR>&) const;
- template
- void
- DoFCellAccessor<DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::set_dof_values_by_interpolation
- (const Vector<SCALAR>&, VEC&) const;
-
-#endif
-
-#if deal_II_dimension == 3
-
- template
- void
- DoFCellAccessor<DoFHandler<1,3>, lda>::get_interpolated_dof_values
- (const VEC&, Vector<SCALAR>&) const;
- template
- void
- DoFCellAccessor<DoFHandler<1,3>, lda>::set_dof_values_by_interpolation
- (const Vector<SCALAR>&, VEC&) const;
-
-#endif
-
- }
-
-
-for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
- {
- template
- void
- DoFCellAccessor<hp::DoFHandler<deal_II_dimension>, lda>::get_interpolated_dof_values
- (const VEC&, Vector<SCALAR>&) const;
- template
- void
- DoFCellAccessor<hp::DoFHandler<deal_II_dimension>, lda>::set_dof_values_by_interpolation
- (const Vector<SCALAR>&, VEC&) const;
-
-#if deal_II_dimension != 3
-
- template
- void
- DoFCellAccessor<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::get_interpolated_dof_values
- (const VEC&, Vector<SCALAR>&) const;
- template
- void
- DoFCellAccessor<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::set_dof_values_by_interpolation
- (const Vector<SCALAR>&, VEC&) const;
-
-#endif
-
-#if deal_II_dimension == 3
-
- template
- void
- DoFCellAccessor<hp::DoFHandler<1,3>, lda>::get_interpolated_dof_values
- (const VEC&, Vector<SCALAR>&) const;
- template
- void
- DoFCellAccessor<hp::DoFHandler<1,3>, lda>::set_dof_values_by_interpolation
- (const Vector<SCALAR>&, VEC&) const;
-
-#endif
- }
-
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/lac/sparse_matrix.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_levels.h>
+#include <deal.II/hp/dof_handler.h>
+#include <deal.II/grid/tria_boundary.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/tria_iterator.templates.h>
+#include <deal.II/fe/fe.h>
+
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+template <class DH, bool lda>
+template <class InputVector, typename number>
+void
+DoFCellAccessor<DH,lda>::
+get_interpolated_dof_values (const InputVector &values,
+ Vector<number> &interpolated_values) const
+{
+ const FiniteElement<dim,spacedim> &fe = this->get_fe();
+ const unsigned int dofs_per_cell = fe.dofs_per_cell;
+
+ Assert (this->dof_handler != 0,
+ typename BaseClass::ExcInvalidObject());
+ Assert (&fe != 0,
+ typename BaseClass::ExcInvalidObject());
+ Assert (interpolated_values.size() == dofs_per_cell,
+ typename BaseClass::ExcVectorDoesNotMatch());
+ Assert (values.size() == this->dof_handler->n_dofs(),
+ typename BaseClass::ExcVectorDoesNotMatch());
+
+ if (!this->has_children())
+ // if this cell has no children: simply return the exact values on this
+ // cell
+ this->get_dof_values (values, interpolated_values);
+ else
+ // otherwise clobber them from the children
+ {
+ Vector<number> tmp1(dofs_per_cell);
+ Vector<number> tmp2(dofs_per_cell);
+
+ interpolated_values = 0;
+
+ // later on we will have to push the values interpolated from the child
+ // to the mother cell into the output vector. unfortunately, there are
+ // two types of elements: ones where you add up the contributions from
+ // the different child cells, and ones where you overwrite.
+ //
+ // an example for the first is piecewise constant (and discontinuous)
+ // elements, where we build the value on the coarse cell by averaging
+ // the values from the cell (i.e. by adding up a fraction of the values
+ // of their values)
+ //
+ // an example for the latter are the usual continuous elements. the
+ // value on a vertex of a coarse cell must there be the same,
+ // irrespective of the adjacent cell we are presently on. so we always
+ // overwrite. in fact, we must, since we cannot know in advance how many
+ // neighbors there will be, so there is no way to compute the average
+ // with fixed factors
+ //
+ // so we have to find out to which type this element belongs. the
+ // difficulty is: the finite element may be a composed one, so we can
+ // only hope to do this for each shape function individually. in fact,
+ // there are even weird finite elements (for example the Raviart-Thomas
+ // element) which have shape functions that are additive (interior ones)
+ // and others that are overwriting (face degrees of freedom that need to
+ // be continuous across the face). to avoid checking this over and over
+ // again, we do this once now and cache the results
+ std::vector<bool> restriction_is_additive (dofs_per_cell);
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ restriction_is_additive[i] = fe.restriction_is_additive(i);
+
+ for (unsigned int child=0; child<this->n_children(); ++child)
+ {
+ // get the values from the present child, if necessary by
+ // interpolation itself
+ this->child(child)->get_interpolated_dof_values (values,
+ tmp1);
+ // interpolate these to the mother cell
+ fe.get_restriction_matrix(child, this->refinement_case()).vmult (tmp2, tmp1);
+
+ // and add up or set them in the output vector
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ if (restriction_is_additive[i])
+ interpolated_values(i) += tmp2(i);
+ else if (tmp2(i) != number())
+ interpolated_values(i) = tmp2(i);
+ }
+ }
+}
+
+
+// --------------------------------------------------------------------------
+// explicit instantiations
+#include "dof_accessor_get.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+
+for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
+ {
+ template
+ void
+ DoFCellAccessor<DoFHandler<deal_II_dimension>, lda>::get_interpolated_dof_values
+ (const VEC&, Vector<SCALAR>&) const;
+
+#if deal_II_dimension != 3
+
+ template
+ void
+ DoFCellAccessor<DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::get_interpolated_dof_values
+ (const VEC&, Vector<SCALAR>&) const;
+
+#endif
+
+#if deal_II_dimension == 3
+
+ template
+ void
+ DoFCellAccessor<DoFHandler<1,3>, lda>::get_interpolated_dof_values
+ (const VEC&, Vector<SCALAR>&) const;
+
+#endif
+
+ }
+
+
+for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
+ {
+ template
+ void
+ DoFCellAccessor<hp::DoFHandler<deal_II_dimension>, lda>::get_interpolated_dof_values
+ (const VEC&, Vector<SCALAR>&) const;
+
+#if deal_II_dimension != 3
+
+ template
+ void
+ DoFCellAccessor<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::get_interpolated_dof_values
+ (const VEC&, Vector<SCALAR>&) const;
+
+#endif
+
+#if deal_II_dimension == 3
+
+ template
+ void
+ DoFCellAccessor<hp::DoFHandler<1,3>, lda>::get_interpolated_dof_values
+ (const VEC&, Vector<SCALAR>&) const;
+
+#endif
+ }
+
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/lac/sparse_matrix.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_levels.h>
+#include <deal.II/hp/dof_handler.h>
+#include <deal.II/grid/tria_boundary.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/tria_iterator.templates.h>
+#include <deal.II/fe/fe.h>
+
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+template <class DH, bool lda>
+template <class OutputVector, typename number>
+void
+DoFCellAccessor<DH,lda>::
+set_dof_values_by_interpolation (const Vector<number> &local_values,
+ OutputVector &values) const
+{
+ const unsigned int dofs_per_cell = this->get_fe().dofs_per_cell;
+
+ Assert (this->dof_handler != 0,
+ typename BaseClass::ExcInvalidObject());
+ Assert (&this->get_fe() != 0,
+ typename BaseClass::ExcInvalidObject());
+ Assert (local_values.size() == dofs_per_cell,
+ typename BaseClass::ExcVectorDoesNotMatch());
+ Assert (values.size() == this->dof_handler->n_dofs(),
+ typename BaseClass::ExcVectorDoesNotMatch());
+
+ if (!this->has_children())
+ // if this cell has no children: simply set the values on this cell
+ this->set_dof_values (local_values, values);
+ else
+ // otherwise distribute them to the children
+ {
+ Vector<number> tmp(dofs_per_cell);
+
+ for (unsigned int child=0; child<this->n_children(); ++child)
+ {
+ Assert (this->child(child)->get_fe().dofs_per_cell == dofs_per_cell,
+ ExcNotImplemented());
+
+ // prolong the given data to the present cell. FullMatrix only wants
+ // us to call vmult if the matrix size is actually non-zero, so
+ // check that case
+ if (tmp.size() > 0)
+ {
+ this->get_fe().get_prolongation_matrix(child, this->refinement_case())
+ .vmult (tmp, local_values);
+
+ this->child(child)->set_dof_values_by_interpolation (tmp, values);
+ }
+ }
+ }
+}
+
+
+
+// --------------------------------------------------------------------------
+// explicit instantiations
+#include "dof_accessor_set.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+
+for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
+ {
+ template
+ void
+ DoFCellAccessor<DoFHandler<deal_II_dimension>, lda>::set_dof_values_by_interpolation
+ (const Vector<SCALAR>&, VEC&) const;
+
+#if deal_II_dimension != 3
+
+ template
+ void
+ DoFCellAccessor<DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::set_dof_values_by_interpolation
+ (const Vector<SCALAR>&, VEC&) const;
+
+#endif
+
+#if deal_II_dimension == 3
+
+ template
+ void
+ DoFCellAccessor<DoFHandler<1,3>, lda>::set_dof_values_by_interpolation
+ (const Vector<SCALAR>&, VEC&) const;
+
+#endif
+
+ }
+
+
+for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
+ {
+ template
+ void
+ DoFCellAccessor<hp::DoFHandler<deal_II_dimension>, lda>::set_dof_values_by_interpolation
+ (const Vector<SCALAR>&, VEC&) const;
+
+#if deal_II_dimension != 3
+
+ template
+ void
+ DoFCellAccessor<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::set_dof_values_by_interpolation
+ (const Vector<SCALAR>&, VEC&) const;
+
+#endif
+
+#if deal_II_dimension == 3
+
+ template
+ void
+ DoFCellAccessor<hp::DoFHandler<1,3>, lda>::set_dof_values_by_interpolation
+ (const Vector<SCALAR>&, VEC&) const;
+
+#endif
+ }
+
#include <deal.II/hp/q_collection.h>
#include <deal.II/hp/fe_values.h>
#include <deal.II/dofs/dof_tools.h>
-#include <deal.II/numerics/vector_tools.h>
#include <deal.II/multigrid/mg_dof_handler.h>
namespace DoFTools
{
-
- template <class DH, class SparsityPattern>
- void
- make_sparsity_pattern (const DH &dof,
- SparsityPattern &sparsity,
- const ConstraintMatrix &constraints,
- const bool keep_constrained_dofs,
- const types::subdomain_id subdomain_id)
- {
- const types::global_dof_index n_dofs = dof.n_dofs();
-
- Assert (sparsity.n_rows() == n_dofs,
- ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
- Assert (sparsity.n_cols() == n_dofs,
- ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
-
- // If we have a distributed::Triangulation only allow locally_owned
- // subdomain. Not setting a subdomain is also okay, because we skip
- // ghost cells in the loop below.
- Assert (
- (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == dof.get_tria().locally_owned_subdomain()),
- ExcMessage ("For parallel::distributed::Triangulation objects and "
- "associated DoF handler objects, asking for any subdomain other "
- "than the locally owned one does not make sense."));
-
- std::vector<types::global_dof_index> dofs_on_this_cell;
- dofs_on_this_cell.reserve (max_dofs_per_cell(dof));
- typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
-
- // In case we work with a distributed sparsity pattern of Trilinos
- // type, we only have to do the work if the current cell is owned by
- // the calling processor. Otherwise, just continue.
- for (; cell!=endc; ++cell)
- if (((subdomain_id == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == cell->subdomain_id()))
- &&
- cell->is_locally_owned())
- {
- const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
- dofs_on_this_cell.resize (dofs_per_cell);
- cell->get_dof_indices (dofs_on_this_cell);
-
- // make sparsity pattern for this cell. if no constraints pattern
- // was given, then the following call acts as if simply no
- // constraints existed
- constraints.add_entries_local_to_global (dofs_on_this_cell,
- sparsity,
- keep_constrained_dofs);
- }
- }
-
-
-
- template <class DH, class SparsityPattern>
- void
- make_sparsity_pattern (const DH &dof,
- const Table<2,Coupling> &couplings,
- SparsityPattern &sparsity,
- const ConstraintMatrix &constraints,
- const bool keep_constrained_dofs,
- const types::subdomain_id subdomain_id)
- {
- const types::global_dof_index n_dofs = dof.n_dofs();
-
- Assert (sparsity.n_rows() == n_dofs,
- ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
- Assert (sparsity.n_cols() == n_dofs,
- ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
- Assert (couplings.n_rows() == dof.get_fe().n_components(),
- ExcDimensionMismatch(couplings.n_rows(), dof.get_fe().n_components()));
- Assert (couplings.n_cols() == dof.get_fe().n_components(),
- ExcDimensionMismatch(couplings.n_cols(), dof.get_fe().n_components()));
-
- // If we have a distributed::Triangulation only allow locally_owned
- // subdomain. Not setting a subdomain is also okay, because we skip
- // ghost cells in the loop below.
- Assert (
- (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == dof.get_tria().locally_owned_subdomain()),
- ExcMessage ("For parallel::distributed::Triangulation objects and "
- "associated DoF handler objects, asking for any subdomain other "
- "than the locally owned one does not make sense."));
-
- const hp::FECollection<DH::dimension,DH::space_dimension> fe_collection (dof.get_fe());
-
- // first, for each finite element, build a mask for each dof, not like
- // the one given which represents components. make sure we do the right
- // thing also with respect to non-primitive shape functions, which
- // takes some additional thought
- std::vector<Table<2,bool> > dof_mask(fe_collection.size());
-
- // check whether the table of couplings contains only true arguments,
- // i.e., we do not exclude any index. that is the easy case, since we
- // don't have to set up the tables
- bool need_dof_mask = false;
- for (unsigned int i=0; i<couplings.n_rows(); ++i)
- for (unsigned int j=0; j<couplings.n_cols(); ++j)
- if (couplings(i,j) == none)
- need_dof_mask = true;
-
- if (need_dof_mask == true)
- for (unsigned int f=0; f<fe_collection.size(); ++f)
- {
- const unsigned int dofs_per_cell = fe_collection[f].dofs_per_cell;
-
- dof_mask[f].reinit (dofs_per_cell, dofs_per_cell);
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- if (fe_collection[f].is_primitive(i) &&
- fe_collection[f].is_primitive(j))
- dof_mask[f](i,j)
- = (couplings(fe_collection[f].system_to_component_index(i).first,
- fe_collection[f].system_to_component_index(j).first) != none);
- else
- {
- const unsigned int first_nonzero_comp_i
- = fe_collection[f].get_nonzero_components(i).first_selected_component();
- const unsigned int first_nonzero_comp_j
- = fe_collection[f].get_nonzero_components(j).first_selected_component();
- Assert (first_nonzero_comp_i < fe_collection[f].n_components(),
- ExcInternalError());
- Assert (first_nonzero_comp_j < fe_collection[f].n_components(),
- ExcInternalError());
-
- dof_mask[f](i,j)
- = (couplings(first_nonzero_comp_i,first_nonzero_comp_j) != none);
- }
- }
-
-
- std::vector<types::global_dof_index> dofs_on_this_cell(fe_collection.max_dofs_per_cell());
- typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
-
- // In case we work with a distributed sparsity pattern of Trilinos
- // type, we only have to do the work if the current cell is owned by
- // the calling processor. Otherwise, just continue.
- for (; cell!=endc; ++cell)
- if (((subdomain_id == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == cell->subdomain_id()))
- &&
- cell->is_locally_owned())
- {
- const unsigned int fe_index = cell->active_fe_index();
- const unsigned int dofs_per_cell =fe_collection[fe_index].dofs_per_cell;
-
- dofs_on_this_cell.resize (dofs_per_cell);
- cell->get_dof_indices (dofs_on_this_cell);
-
-
- // make sparsity pattern for this cell. if no constraints pattern
- // was given, then the following call acts as if simply no
- // constraints existed
- constraints.add_entries_local_to_global (dofs_on_this_cell,
- sparsity,
- keep_constrained_dofs,
- dof_mask[fe_index]);
- }
- }
-
-
-
- template <class DH, class SparsityPattern>
- void
- make_sparsity_pattern (
- const DH &dof_row,
- const DH &dof_col,
- SparsityPattern &sparsity)
- {
- const types::global_dof_index n_dofs_row = dof_row.n_dofs();
- const types::global_dof_index n_dofs_col = dof_col.n_dofs();
-
- Assert (sparsity.n_rows() == n_dofs_row,
- ExcDimensionMismatch (sparsity.n_rows(), n_dofs_row));
- Assert (sparsity.n_cols() == n_dofs_col,
- ExcDimensionMismatch (sparsity.n_cols(), n_dofs_col));
-
-//TODO: Looks like wasteful memory management here
-
- const std::list<std::pair<typename DH::cell_iterator,
- typename DH::cell_iterator> >
- cell_list
- = GridTools::get_finest_common_cells (dof_row, dof_col);
-
-
- typename std::list<std::pair<typename DH::cell_iterator,
- typename DH::cell_iterator> >::const_iterator
- cell_iter = cell_list.begin();
-
- for (; cell_iter!=cell_list.end(); ++cell_iter)
- {
- const typename DH::cell_iterator cell_row = cell_iter->first;
- const typename DH::cell_iterator cell_col = cell_iter->second;
-
- if (!cell_row->has_children() && !cell_col->has_children())
- {
- const unsigned int dofs_per_cell_row =
- cell_row->get_fe().dofs_per_cell;
- const unsigned int dofs_per_cell_col =
- cell_col->get_fe().dofs_per_cell;
- std::vector<types::global_dof_index>
- local_dof_indices_row(dofs_per_cell_row);
- std::vector<types::global_dof_index>
- local_dof_indices_col(dofs_per_cell_col);
- cell_row->get_dof_indices (local_dof_indices_row);
- cell_col->get_dof_indices (local_dof_indices_col);
- for (unsigned int i=0; i<dofs_per_cell_row; ++i)
- sparsity.add_entries (local_dof_indices_row[i],
- local_dof_indices_col.begin(),
- local_dof_indices_col.end());
- }
- else if (cell_row->has_children())
- {
- const std::vector<typename DH::active_cell_iterator >
- child_cells = GridTools::get_active_child_cells<DH> (cell_row);
- for (unsigned int i=0; i<child_cells.size(); i++)
- {
- const typename DH::cell_iterator
- cell_row_child = child_cells[i];
- const unsigned int dofs_per_cell_row =
- cell_row_child->get_fe().dofs_per_cell;
- const unsigned int dofs_per_cell_col =
- cell_col->get_fe().dofs_per_cell;
- std::vector<types::global_dof_index>
- local_dof_indices_row(dofs_per_cell_row);
- std::vector<types::global_dof_index>
- local_dof_indices_col(dofs_per_cell_col);
- cell_row_child->get_dof_indices (local_dof_indices_row);
- cell_col->get_dof_indices (local_dof_indices_col);
- for (unsigned int i=0; i<dofs_per_cell_row; ++i)
- sparsity.add_entries (local_dof_indices_row[i],
- local_dof_indices_col.begin(),
- local_dof_indices_col.end());
- }
- }
- else
- {
- std::vector<typename DH::active_cell_iterator>
- child_cells = GridTools::get_active_child_cells<DH> (cell_col);
- for (unsigned int i=0; i<child_cells.size(); i++)
- {
- const typename DH::active_cell_iterator
- cell_col_child = child_cells[i];
- const unsigned int dofs_per_cell_row =
- cell_row->get_fe().dofs_per_cell;
- const unsigned int dofs_per_cell_col =
- cell_col_child->get_fe().dofs_per_cell;
- std::vector<types::global_dof_index>
- local_dof_indices_row(dofs_per_cell_row);
- std::vector<types::global_dof_index>
- local_dof_indices_col(dofs_per_cell_col);
- cell_row->get_dof_indices (local_dof_indices_row);
- cell_col_child->get_dof_indices (local_dof_indices_col);
- for (unsigned int i=0; i<dofs_per_cell_row; ++i)
- sparsity.add_entries (local_dof_indices_row[i],
- local_dof_indices_col.begin(),
- local_dof_indices_col.end());
- }
- }
- }
- }
-
-
-
- template <class DH, class SparsityPattern>
- void
- make_boundary_sparsity_pattern (
- const DH &dof,
- const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- SparsityPattern &sparsity)
- {
- if (DH::dimension == 1)
- {
- // there are only 2 boundary indicators in 1d, so it is no
- // performance problem to call the other function
- typename DH::FunctionMap boundary_indicators;
- boundary_indicators[0] = 0;
- boundary_indicators[1] = 0;
- make_boundary_sparsity_pattern<DH, SparsityPattern> (dof,
- boundary_indicators,
- dof_to_boundary_mapping,
- sparsity);
- return;
- }
-
- const types::global_dof_index n_dofs = dof.n_dofs();
-
- AssertDimension (dof_to_boundary_mapping.size(), n_dofs);
- AssertDimension (sparsity.n_rows(), dof.n_boundary_dofs());
- AssertDimension (sparsity.n_cols(), dof.n_boundary_dofs());
-#ifdef DEBUG
- if (sparsity.n_rows() != 0)
- {
- types::global_dof_index max_element = 0;
- for (std::vector<types::global_dof_index>::const_iterator i=dof_to_boundary_mapping.begin();
- i!=dof_to_boundary_mapping.end(); ++i)
- if ((*i != DH::invalid_dof_index) &&
- (*i > max_element))
- max_element = *i;
- AssertDimension (max_element, sparsity.n_rows()-1);
- };
-#endif
-
- std::vector<types::global_dof_index> dofs_on_this_face;
- dofs_on_this_face.reserve (max_dofs_per_face(dof));
-
- // loop over all faces to check whether they are at a boundary. note
- // that we need not take special care of single lines (using
- // @p{cell->has_boundary_lines}), since we do not support boundaries of
- // dimension dim-2, and so every boundary line is also part of a
- // boundary face.
- typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
- for (; cell!=endc; ++cell)
- for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
- if (cell->at_boundary(f))
- {
- const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
- dofs_on_this_face.resize (dofs_per_face);
- cell->face(f)->get_dof_indices (dofs_on_this_face,
- cell->active_fe_index());
-
- // make sparsity pattern for this cell
- for (unsigned int i=0; i<dofs_per_face; ++i)
- for (unsigned int j=0; j<dofs_per_face; ++j)
- sparsity.add (dof_to_boundary_mapping[dofs_on_this_face[i]],
- dof_to_boundary_mapping[dofs_on_this_face[j]]);
- }
- }
-
-
-
- template <class DH, class SparsityPattern>
- void make_boundary_sparsity_pattern (
- const DH &dof,
- const typename FunctionMap<DH::space_dimension>::type &boundary_indicators,
- const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- SparsityPattern &sparsity)
- {
- if (DH::dimension == 1)
- {
- // first check left, then right boundary point
- for (unsigned int direction=0; direction<2; ++direction)
- {
- // if this boundary is not requested, then go on with next one
- if (boundary_indicators.find(direction) ==
- boundary_indicators.end())
- continue;
-
- // find active cell at that boundary: first go to left/right,
- // then to children
- typename DH::level_cell_iterator cell = dof.begin(0);
- while (!cell->at_boundary(direction))
- cell = cell->neighbor(direction);
- while (!cell->active())
- cell = cell->child(direction);
-
- const unsigned int dofs_per_vertex = cell->get_fe().dofs_per_vertex;
- std::vector<types::global_dof_index> boundary_dof_boundary_indices (dofs_per_vertex);
-
- // next get boundary mapped dof indices of boundary dofs
- for (unsigned int i=0; i<dofs_per_vertex; ++i)
- boundary_dof_boundary_indices[i]
- = dof_to_boundary_mapping[cell->vertex_dof_index(direction,i)];
-
- for (unsigned int i=0; i<dofs_per_vertex; ++i)
- sparsity.add_entries (boundary_dof_boundary_indices[i],
- boundary_dof_boundary_indices.begin(),
- boundary_dof_boundary_indices.end());
- };
- return;
- }
-
- const types::global_dof_index n_dofs = dof.n_dofs();
-
- AssertDimension (dof_to_boundary_mapping.size(), n_dofs);
- Assert (boundary_indicators.find(numbers::internal_face_boundary_id) == boundary_indicators.end(),
- typename DH::ExcInvalidBoundaryIndicator());
- Assert (sparsity.n_rows() == dof.n_boundary_dofs (boundary_indicators),
- ExcDimensionMismatch (sparsity.n_rows(), dof.n_boundary_dofs (boundary_indicators)));
- Assert (sparsity.n_cols() == dof.n_boundary_dofs (boundary_indicators),
- ExcDimensionMismatch (sparsity.n_cols(), dof.n_boundary_dofs (boundary_indicators)));
-#ifdef DEBUG
- if (sparsity.n_rows() != 0)
- {
- types::global_dof_index max_element = 0;
- for (std::vector<types::global_dof_index>::const_iterator i=dof_to_boundary_mapping.begin();
- i!=dof_to_boundary_mapping.end(); ++i)
- if ((*i != DH::invalid_dof_index) &&
- (*i > max_element))
- max_element = *i;
- AssertDimension (max_element, sparsity.n_rows()-1);
- };
-#endif
-
- std::vector<types::global_dof_index> dofs_on_this_face;
- dofs_on_this_face.reserve (max_dofs_per_face(dof));
- typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
- for (; cell!=endc; ++cell)
- for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
- if (boundary_indicators.find(cell->face(f)->boundary_indicator()) !=
- boundary_indicators.end())
- {
- const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
- dofs_on_this_face.resize (dofs_per_face);
- cell->face(f)->get_dof_indices (dofs_on_this_face,
- cell->active_fe_index());
-
- // make sparsity pattern for this cell
- for (unsigned int i=0; i<dofs_per_face; ++i)
- for (unsigned int j=0; j<dofs_per_face; ++j)
- sparsity.add (dof_to_boundary_mapping[dofs_on_this_face[i]],
- dof_to_boundary_mapping[dofs_on_this_face[j]]);
- }
- }
-
-
-
- template <class DH, class SparsityPattern>
- void
- make_flux_sparsity_pattern (const DH &dof,
- SparsityPattern &sparsity,
- const ConstraintMatrix &constraints,
- const bool keep_constrained_dofs,
- const types::subdomain_id subdomain_id)
-
- // TODO: QA: reduce the indentation level of this method..., Maier 2012
-
- {
- const types::global_dof_index n_dofs = dof.n_dofs();
-
- AssertDimension (sparsity.n_rows(), n_dofs);
- AssertDimension (sparsity.n_cols(), n_dofs);
-
- // If we have a distributed::Triangulation only allow locally_owned
- // subdomain. Not setting a subdomain is also okay, because we skip
- // ghost cells in the loop below.
- Assert (
- (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == dof.get_tria().locally_owned_subdomain()),
- ExcMessage ("For parallel::distributed::Triangulation objects and "
- "associated DoF handler objects, asking for any subdomain other "
- "than the locally owned one does not make sense."));
-
- std::vector<types::global_dof_index> dofs_on_this_cell;
- std::vector<types::global_dof_index> dofs_on_other_cell;
- dofs_on_this_cell.reserve (max_dofs_per_cell(dof));
- dofs_on_other_cell.reserve (max_dofs_per_cell(dof));
- typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
-
- // TODO: in an old implementation, we used user flags before to tag
- // faces that were already touched. this way, we could reduce the work
- // a little bit. now, we instead add only data from one side. this
- // should be OK, but we need to actually verify it.
-
- // In case we work with a distributed sparsity pattern of Trilinos
- // type, we only have to do the work if the current cell is owned by
- // the calling processor. Otherwise, just continue.
- for (; cell!=endc; ++cell)
- if (((subdomain_id == numbers::invalid_subdomain_id)
- ||
- (subdomain_id == cell->subdomain_id()))
- &&
- cell->is_locally_owned())
- {
- const unsigned int n_dofs_on_this_cell = cell->get_fe().dofs_per_cell;
- dofs_on_this_cell.resize (n_dofs_on_this_cell);
- cell->get_dof_indices (dofs_on_this_cell);
-
- // make sparsity pattern for this cell. if no constraints pattern
- // was given, then the following call acts as if simply no
- // constraints existed
- constraints.add_entries_local_to_global (dofs_on_this_cell,
- sparsity,
- keep_constrained_dofs);
-
- for (unsigned int face = 0;
- face < GeometryInfo<DH::dimension>::faces_per_cell;
- ++face)
- {
- typename DH::face_iterator cell_face = cell->face(face);
- if (! cell->at_boundary(face) )
- {
- typename DH::level_cell_iterator neighbor = cell->neighbor(face);
-
- // in 1d, we do not need to worry whether the neighbor
- // might have children and then loop over those children.
- // rather, we may as well go straight to to cell behind
- // this particular cell's most terminal child
- if (DH::dimension==1)
- while (neighbor->has_children())
- neighbor = neighbor->child(face==0 ? 1 : 0);
-
- if (neighbor->has_children())
- {
- for (unsigned int sub_nr = 0;
- sub_nr != cell_face->number_of_children();
- ++sub_nr)
- {
- const typename DH::level_cell_iterator
- sub_neighbor
- = cell->neighbor_child_on_subface (face, sub_nr);
-
- const unsigned int n_dofs_on_neighbor
- = sub_neighbor->get_fe().dofs_per_cell;
- dofs_on_other_cell.resize (n_dofs_on_neighbor);
- sub_neighbor->get_dof_indices (dofs_on_other_cell);
-
- constraints.add_entries_local_to_global
- (dofs_on_this_cell, dofs_on_other_cell,
- sparsity, keep_constrained_dofs);
- constraints.add_entries_local_to_global
- (dofs_on_other_cell, dofs_on_this_cell,
- sparsity, keep_constrained_dofs);
- }
- }
- else
- {
- // Refinement edges are taken care of by coarser
- // cells
-
- // TODO: in the distributed case, we miss out the
- // constraints when the neighbor cell is coarser, but
- // only the current cell is owned locally!
- if (cell->neighbor_is_coarser(face))
- continue;
-
- const unsigned int n_dofs_on_neighbor
- = neighbor->get_fe().dofs_per_cell;
- dofs_on_other_cell.resize (n_dofs_on_neighbor);
-
- neighbor->get_dof_indices (dofs_on_other_cell);
-
- constraints.add_entries_local_to_global
- (dofs_on_this_cell, dofs_on_other_cell,
- sparsity, keep_constrained_dofs);
-
- // only need to add these in case the neighbor cell
- // is not locally owned - otherwise, we touch each
- // face twice and hence put the indices the other way
- // around
- if (!cell->neighbor(face)->active()
- ||
- (cell->neighbor(face)->subdomain_id() !=
- cell->subdomain_id()))
- constraints.add_entries_local_to_global
- (dofs_on_other_cell, dofs_on_this_cell,
- sparsity, keep_constrained_dofs);
- }
- }
- }
- }
- }
-
-
-
- template <class DH, class SparsityPattern>
- void
- make_flux_sparsity_pattern (const DH &dof,
- SparsityPattern &sparsity)
- {
- ConstraintMatrix constraints;
- make_flux_sparsity_pattern (dof, sparsity, constraints);
- }
-
-
-
- template <int dim, int spacedim>
- Table<2,Coupling>
- dof_couplings_from_component_couplings (const FiniteElement<dim,spacedim> &fe,
- const Table<2,Coupling> &component_couplings)
- {
- Assert(component_couplings.n_rows() == fe.n_components(),
- ExcDimensionMismatch(component_couplings.n_rows(),
- fe.n_components()));
- Assert(component_couplings.n_cols() == fe.n_components(),
- ExcDimensionMismatch(component_couplings.n_cols(),
- fe.n_components()));
-
- const unsigned int n_dofs = fe.dofs_per_cell;
-
- Table<2,Coupling> dof_couplings (n_dofs, n_dofs);
-
- for (unsigned int i=0; i<n_dofs; ++i)
- {
- const unsigned int ii
- = (fe.is_primitive(i) ?
- fe.system_to_component_index(i).first
- :
- fe.get_nonzero_components(i).first_selected_component()
- );
- Assert (ii < fe.n_components(), ExcInternalError());
-
- for (unsigned int j=0; j<n_dofs; ++j)
- {
- const unsigned int jj
- = (fe.is_primitive(j) ?
- fe.system_to_component_index(j).first
- :
- fe.get_nonzero_components(j).first_selected_component()
- );
- Assert (jj < fe.n_components(), ExcInternalError());
-
- dof_couplings(i,j) = component_couplings(ii,jj);
- }
- }
- return dof_couplings;
- }
-
-
-
- template <int dim, int spacedim>
- std::vector<Table<2,Coupling> >
- dof_couplings_from_component_couplings
- (const hp::FECollection<dim,spacedim> &fe,
- const Table<2,Coupling> &component_couplings)
- {
- std::vector<Table<2,Coupling> > return_value (fe.size());
- for (unsigned int i=0; i<fe.size(); ++i)
- return_value[i]
- = dof_couplings_from_component_couplings(fe[i], component_couplings);
-
- return return_value;
- }
-
-
-
- namespace internal
- {
- namespace
- {
-
- // implementation of the same function in namespace DoFTools for
- // non-hp DoFHandlers
- template <class DH, class SparsityPattern>
- void
- make_flux_sparsity_pattern (const DH &dof,
- SparsityPattern &sparsity,
- const Table<2,Coupling> &int_mask,
- const Table<2,Coupling> &flux_mask)
- {
- const FiniteElement<DH::dimension,DH::space_dimension> &fe = dof.get_fe();
-
- std::vector<types::global_dof_index> dofs_on_this_cell(fe.dofs_per_cell);
- std::vector<types::global_dof_index> dofs_on_other_cell(fe.dofs_per_cell);
-
- const Table<2,Coupling>
- int_dof_mask = dof_couplings_from_component_couplings(fe, int_mask),
- flux_dof_mask = dof_couplings_from_component_couplings(fe, flux_mask);
-
- Table<2,bool> support_on_face(fe.dofs_per_cell,
- GeometryInfo<DH::dimension>::faces_per_cell);
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
- support_on_face(i,f) = fe.has_support_on_face(i,f);
-
- typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
- for (; cell!=endc; ++cell)
- if (cell->is_locally_owned())
- {
- cell->get_dof_indices (dofs_on_this_cell);
- // make sparsity pattern for this cell
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
- if (int_dof_mask(i,j) != none)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
-
- // Loop over all interior neighbors
- for (unsigned int face = 0;
- face < GeometryInfo<DH::dimension>::faces_per_cell;
- ++face)
- {
- const typename DH::face_iterator
- cell_face = cell->face(face);
- if (cell_face->user_flag_set ())
- continue;
-
- if (cell->at_boundary (face) )
- {
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- {
- const bool i_non_zero_i = support_on_face (i, face);
- for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
- {
- const bool j_non_zero_i = support_on_face (j, face);
-
- if ((flux_dof_mask(i,j) == always)
- ||
- (flux_dof_mask(i,j) == nonzero
- &&
- i_non_zero_i
- &&
- j_non_zero_i))
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- }
- }
- }
- else
- {
- typename DH::level_cell_iterator
- neighbor = cell->neighbor(face);
- // Refinement edges are taken care of by coarser
- // cells
- if (cell->neighbor_is_coarser(face))
- continue;
-
- typename DH::face_iterator cell_face = cell->face(face);
- const unsigned int
- neighbor_face = cell->neighbor_of_neighbor(face);
-
- if (cell_face->has_children())
- {
- for (unsigned int sub_nr = 0;
- sub_nr != cell_face->n_children();
- ++sub_nr)
- {
- const typename DH::level_cell_iterator
- sub_neighbor
- = cell->neighbor_child_on_subface (face, sub_nr);
-
- sub_neighbor->get_dof_indices (dofs_on_other_cell);
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- {
- const bool i_non_zero_i = support_on_face (i, face);
- const bool i_non_zero_e = support_on_face (i, neighbor_face);
- for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
- {
- const bool j_non_zero_i = support_on_face (j, face);
- const bool j_non_zero_e = support_on_face (j, neighbor_face);
-
- if (flux_dof_mask(i,j) == always)
- {
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_other_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_other_cell[j]);
- }
- else if (flux_dof_mask(i,j) == nonzero)
- {
- if (i_non_zero_i && j_non_zero_e)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_other_cell[j]);
- if (i_non_zero_e && j_non_zero_i)
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_this_cell[j]);
- if (i_non_zero_i && j_non_zero_i)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- if (i_non_zero_e && j_non_zero_e)
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_other_cell[j]);
- }
-
- if (flux_dof_mask(j,i) == always)
- {
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_other_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_other_cell[i]);
- }
- else if (flux_dof_mask(j,i) == nonzero)
- {
- if (j_non_zero_i && i_non_zero_e)
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_other_cell[i]);
- if (j_non_zero_e && i_non_zero_i)
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- if (j_non_zero_i && i_non_zero_i)
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_this_cell[i]);
- if (j_non_zero_e && i_non_zero_e)
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_other_cell[i]);
- }
- }
- }
- sub_neighbor->face(neighbor_face)->set_user_flag ();
- }
- }
- else
- {
- neighbor->get_dof_indices (dofs_on_other_cell);
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- {
- const bool i_non_zero_i = support_on_face (i, face);
- const bool i_non_zero_e = support_on_face (i, neighbor_face);
- for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
- {
- const bool j_non_zero_i = support_on_face (j, face);
- const bool j_non_zero_e = support_on_face (j, neighbor_face);
- if (flux_dof_mask(i,j) == always)
- {
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_other_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_other_cell[j]);
- }
- if (flux_dof_mask(i,j) == nonzero)
- {
- if (i_non_zero_i && j_non_zero_e)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_other_cell[j]);
- if (i_non_zero_e && j_non_zero_i)
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_this_cell[j]);
- if (i_non_zero_i && j_non_zero_i)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- if (i_non_zero_e && j_non_zero_e)
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_other_cell[j]);
- }
-
- if (flux_dof_mask(j,i) == always)
- {
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_other_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_other_cell[i]);
- }
- if (flux_dof_mask(j,i) == nonzero)
- {
- if (j_non_zero_i && i_non_zero_e)
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_other_cell[i]);
- if (j_non_zero_e && i_non_zero_i)
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- if (j_non_zero_i && i_non_zero_i)
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_this_cell[i]);
- if (j_non_zero_e && i_non_zero_e)
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_other_cell[i]);
- }
- }
- }
- neighbor->face(neighbor_face)->set_user_flag ();
- }
- }
- }
- }
- }
-
-
- // implementation of the same function in namespace DoFTools for
- // non-hp DoFHandlers
- template <int dim, int spacedim, class SparsityPattern>
- void
- make_flux_sparsity_pattern (const dealii::hp::DoFHandler<dim,spacedim> &dof,
- SparsityPattern &sparsity,
- const Table<2,Coupling> &int_mask,
- const Table<2,Coupling> &flux_mask)
- {
- // while the implementation above is quite optimized and caches a
- // lot of data (see e.g. the int/flux_dof_mask tables), this is no
- // longer practical for the hp version since we would have to have
- // it for all combinations of elements in the hp::FECollection.
- // consequently, the implementation here is simpler and probably
- // less efficient but at least readable...
-
- const dealii::hp::FECollection<dim,spacedim> &fe = dof.get_fe();
-
- std::vector<types::global_dof_index> dofs_on_this_cell(DoFTools::max_dofs_per_cell(dof));
- std::vector<types::global_dof_index> dofs_on_other_cell(DoFTools::max_dofs_per_cell(dof));
-
- const std::vector<Table<2,Coupling> >
- int_dof_mask
- = dof_couplings_from_component_couplings(fe, int_mask);
-
- typename dealii::hp::DoFHandler<dim,spacedim>::active_cell_iterator
- cell = dof.begin_active(),
- endc = dof.end();
- for (; cell!=endc; ++cell)
- {
- dofs_on_this_cell.resize (cell->get_fe().dofs_per_cell);
- cell->get_dof_indices (dofs_on_this_cell);
-
- // make sparsity pattern for this cell
- for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
- for (unsigned int j=0; j<cell->get_fe().dofs_per_cell; ++j)
- if (int_dof_mask[cell->active_fe_index()](i,j) != none)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
-
- // Loop over all interior neighbors
- for (unsigned int face = 0;
- face < GeometryInfo<dim>::faces_per_cell;
- ++face)
- {
- const typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
- cell_face = cell->face(face);
- if (cell_face->user_flag_set ())
- continue;
-
- if (cell->at_boundary (face) )
- {
- for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
- for (unsigned int j=0; j<cell->get_fe().dofs_per_cell; ++j)
- if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
- cell->get_fe().system_to_component_index(j).first)
- == always)
- ||
- (flux_mask(cell->get_fe().system_to_component_index(i).first,
- cell->get_fe().system_to_component_index(j).first)
- == nonzero))
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- }
- else
- {
- typename dealii::hp::DoFHandler<dim,spacedim>::level_cell_iterator
- neighbor = cell->neighbor(face);
-
- // Refinement edges are taken care of by coarser cells
- if (cell->neighbor_is_coarser(face))
- continue;
-
- typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
- cell_face = cell->face(face);
- const unsigned int
- neighbor_face = cell->neighbor_of_neighbor(face);
-
- if (cell_face->has_children())
- {
- for (unsigned int sub_nr = 0;
- sub_nr != cell_face->n_children();
- ++sub_nr)
- {
- const typename dealii::hp::DoFHandler<dim,spacedim>::level_cell_iterator
- sub_neighbor
- = cell->neighbor_child_on_subface (face, sub_nr);
-
- dofs_on_other_cell.resize (sub_neighbor->get_fe().dofs_per_cell);
- sub_neighbor->get_dof_indices (dofs_on_other_cell);
- for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<sub_neighbor->get_fe().dofs_per_cell;
- ++j)
- {
- if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
- sub_neighbor->get_fe().system_to_component_index(j).first)
- == always)
- ||
- (flux_mask(cell->get_fe().system_to_component_index(i).first,
- sub_neighbor->get_fe().system_to_component_index(j).first)
- == nonzero))
- {
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_other_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_other_cell[j]);
- }
-
- if ((flux_mask(sub_neighbor->get_fe().system_to_component_index(j).first,
- cell->get_fe().system_to_component_index(i).first)
- == always)
- ||
- (flux_mask(sub_neighbor->get_fe().system_to_component_index(j).first,
- cell->get_fe().system_to_component_index(i).first)
- == nonzero))
- {
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_other_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_other_cell[i]);
- }
- }
- }
- sub_neighbor->face(neighbor_face)->set_user_flag ();
- }
- }
- else
- {
- dofs_on_other_cell.resize (neighbor->get_fe().dofs_per_cell);
- neighbor->get_dof_indices (dofs_on_other_cell);
- for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<neighbor->get_fe().dofs_per_cell; ++j)
- {
- if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
- neighbor->get_fe().system_to_component_index(j).first)
- == always)
- ||
- (flux_mask(cell->get_fe().system_to_component_index(i).first,
- neighbor->get_fe().system_to_component_index(j).first)
- == nonzero))
- {
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_other_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_other_cell[j]);
- }
-
- if ((flux_mask(neighbor->get_fe().system_to_component_index(j).first,
- cell->get_fe().system_to_component_index(i).first)
- == always)
- ||
- (flux_mask(neighbor->get_fe().system_to_component_index(j).first,
- cell->get_fe().system_to_component_index(i).first)
- == nonzero))
- {
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_other_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_other_cell[i]);
- }
- }
- }
- neighbor->face(neighbor_face)->set_user_flag ();
- }
- }
- }
- }
- }
- }
-
- }
-
-
-
-
- template <class DH, class SparsityPattern>
- void
- make_flux_sparsity_pattern (const DH &dof,
- SparsityPattern &sparsity,
- const Table<2,Coupling> &int_mask,
- const Table<2,Coupling> &flux_mask)
- {
- // do the error checking and frame code here, and then pass on to more
- // specialized functions in the internal namespace
- const types::global_dof_index n_dofs = dof.n_dofs();
- const unsigned int n_comp = dof.get_fe().n_components();
-
- Assert (sparsity.n_rows() == n_dofs,
- ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
- Assert (sparsity.n_cols() == n_dofs,
- ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
- Assert (int_mask.n_rows() == n_comp,
- ExcDimensionMismatch (int_mask.n_rows(), n_comp));
- Assert (int_mask.n_cols() == n_comp,
- ExcDimensionMismatch (int_mask.n_cols(), n_comp));
- Assert (flux_mask.n_rows() == n_comp,
- ExcDimensionMismatch (flux_mask.n_rows(), n_comp));
- Assert (flux_mask.n_cols() == n_comp,
- ExcDimensionMismatch (flux_mask.n_cols(), n_comp));
-
- // Clear user flags because we will need them. But first we save them
- // and make sure that we restore them later such that at the end of
- // this function the Triangulation will be in the same state as it was
- // at the beginning of this function.
- std::vector<bool> user_flags;
- dof.get_tria().save_user_flags(user_flags);
- const_cast<Triangulation<DH::dimension,DH::space_dimension> &>(dof.get_tria()).clear_user_flags ();
-
- internal::make_flux_sparsity_pattern (dof, sparsity,
- int_mask, flux_mask);
-
- // finally restore the user flags
- const_cast<Triangulation<DH::dimension,DH::space_dimension> &>(dof.get_tria()).load_user_flags(user_flags);
- }
-
-
-
-
- namespace internal
- {
- namespace
- {
- inline bool
- check_master_dof_list (const FullMatrix<double> &face_interpolation_matrix,
- const std::vector<types::global_dof_index> &master_dof_list)
- {
- const unsigned int N = master_dof_list.size();
-
- FullMatrix<double> tmp (N,N);
- for (unsigned int i=0; i<N; ++i)
- for (unsigned int j=0; j<N; ++j)
- tmp(i,j) = face_interpolation_matrix (master_dof_list[i], j);
-
- // then use the algorithm from FullMatrix::gauss_jordan on this
- // matrix to find out whether it is singular. the algorithm there
- // does piviting and at the end swaps rows back into their proper
- // order -- we omit this step here, since we don't care about the
- // inverse matrix, all we care about is whether the matrix is
- // regular or singular
-
- // first get an estimate of the size of the elements of this
- // matrix, for later checks whether the pivot element is large
- // enough, or whether we have to fear that the matrix is not
- // regular
- double diagonal_sum = 0;
- for (unsigned int i=0; i<N; ++i)
- diagonal_sum += std::fabs(tmp(i,i));
- const double typical_diagonal_element = diagonal_sum/N;
-
- // initialize the array that holds the permutations that we find
- // during pivot search
- std::vector<unsigned int> p(N);
- for (unsigned int i=0; i<N; ++i)
- p[i] = i;
-
- for (unsigned int j=0; j<N; ++j)
- {
- // pivot search: search that part of the line on and right of
- // the diagonal for the largest element
- double max = std::fabs(tmp(j,j));
- unsigned int r = j;
- for (unsigned int i=j+1; i<N; ++i)
- {
- if (std::fabs(tmp(i,j)) > max)
- {
- max = std::fabs(tmp(i,j));
- r = i;
- }
- }
- // check whether the pivot is too small. if that is the case,
- // then the matrix is singular and we shouldn't use this set of
- // master dofs
- if (max < 1.e-12*typical_diagonal_element)
- return false;
-
- // row interchange
- if (r>j)
- {
- for (unsigned int k=0; k<N; ++k)
- std::swap (tmp(j,k), tmp(r,k));
-
- std::swap (p[j], p[r]);
- }
-
- // transformation
- const double hr = 1./tmp(j,j);
- tmp(j,j) = hr;
- for (unsigned int k=0; k<N; ++k)
- {
- if (k==j) continue;
- for (unsigned int i=0; i<N; ++i)
- {
- if (i==j) continue;
- tmp(i,k) -= tmp(i,j)*tmp(j,k)*hr;
- }
- }
- for (unsigned int i=0; i<N; ++i)
- {
- tmp(i,j) *= hr;
- tmp(j,i) *= -hr;
- }
- tmp(j,j) = hr;
- }
-
- // everything went fine, so we can accept this set of master dofs
- // (at least as far as they have already been collected)
- return true;
- }
-
-
-
- /**
- * When restricting, on a face, the degrees of freedom of fe1 to the
- * space described by fe2 (for example for the complex case described
- * in the @ref hp_paper "hp paper"), we have to select
- * fe2.dofs_per_face out of the fe1.dofs_per_face face DoFs as the
- * master DoFs, and the rest become slave dofs. This function selects
- * which ones will be masters, and which ones will be slaves.
- *
- * The function assumes that master_dofs already has size
- * fe1.dofs_per_face. After the function, exactly fe2.dofs_per_face
- * entries will be true.
- *
- * The function is a bit complicated since it has to figure out a set
- * a DoFs so that the corresponding rows in the face interpolation
- * matrix are all linearly independent. we have a good heuristic (see
- * the function body) for selecting these rows, but there are cases
- * where this fails and we have to pick them differently. what we do
- * is to run the heuristic and then go back to determine whether we
- * have a set of rows with full row rank. if this isn't the case, go
- * back and select dofs differently
- */
- template <int dim, int spacedim>
- void
- select_master_dofs_for_face_restriction (const FiniteElement<dim,spacedim> &fe1,
- const FiniteElement<dim,spacedim> &fe2,
- const FullMatrix<double> &face_interpolation_matrix,
- std::vector<bool> &master_dof_mask)
- {
- Assert (fe1.dofs_per_face >= fe2.dofs_per_face,
- ExcInternalError());
- AssertDimension (master_dof_mask.size(), fe1.dofs_per_face);
-
- Assert (fe2.dofs_per_vertex <= fe1.dofs_per_vertex,
- ExcInternalError());
- Assert (fe2.dofs_per_line <= fe1.dofs_per_line,
- ExcInternalError());
- Assert ((dim < 3)
- ||
- (fe2.dofs_per_quad <= fe1.dofs_per_quad),
- ExcInternalError());
-
- // the idea here is to designate as many DoFs in fe1 per object
- // (vertex, line, quad) as master as there are such dofs in fe2
- // (indices are int, because we want to avoid the 'unsigned int < 0
- // is always false warning for the cases at the bottom in 1d and
- // 2d)
- //
- // as mentioned in the paper, it is not always easy to find a set
- // of master dofs that produces an invertible matrix. to this end,
- // we check in each step whether the matrix is still invertible and
- // simply discard this dof if the matrix is not invertible anymore.
- //
- // the cases where we did have trouble in the past were with adding
- // more quad dofs when Q3 and Q4 elements meet at a refined face in
- // 3d (see the hp/crash_12 test that tests that we can do exactly
- // this, and failed before we had code to compensate for this
- // case). the other case are system elements: if we have say a Q1Q2
- // vs a Q2Q3 element, then we can't just take all master dofs on a
- // line from a single base element, since the shape functions of
- // that base element are independent of that of the other one. this
- // latter case shows up when running hp/hp_constraints_q_system_06
-
- std::vector<types::global_dof_index> master_dof_list;
- unsigned int index = 0;
- for (int v=0;
- v<static_cast<signed int>(GeometryInfo<dim>::vertices_per_face);
- ++v)
- {
- unsigned int dofs_added = 0;
- unsigned int i = 0;
- while (dofs_added < fe2.dofs_per_vertex)
- {
- // make sure that we were able to find a set of master dofs
- // and that the code down below didn't just reject all our
- // efforts
- Assert (i < fe1.dofs_per_vertex,
- ExcInternalError());
-
- // tentatively push this vertex dof
- master_dof_list.push_back (index+i);
-
- // then see what happens. if it succeeds, fine
- if (check_master_dof_list (face_interpolation_matrix,
- master_dof_list)
- == true)
- ++dofs_added;
- else
- // well, it didn't. simply pop that dof from the list
- // again and try with the next dof
- master_dof_list.pop_back ();
-
- // forward counter by one
- ++i;
- }
- index += fe1.dofs_per_vertex;
- }
-
- for (int l=0;
- l<static_cast<signed int>(GeometryInfo<dim>::lines_per_face);
- ++l)
- {
- // same algorithm as above
- unsigned int dofs_added = 0;
- unsigned int i = 0;
- while (dofs_added < fe2.dofs_per_line)
- {
- Assert (i < fe1.dofs_per_line,
- ExcInternalError());
-
- master_dof_list.push_back (index+i);
- if (check_master_dof_list (face_interpolation_matrix,
- master_dof_list)
- == true)
- ++dofs_added;
- else
- master_dof_list.pop_back ();
-
- ++i;
- }
- index += fe1.dofs_per_line;
- }
-
- for (int q=0;
- q<static_cast<signed int>(GeometryInfo<dim>::quads_per_face);
- ++q)
- {
- // same algorithm as above
- unsigned int dofs_added = 0;
- unsigned int i = 0;
- while (dofs_added < fe2.dofs_per_quad)
- {
- Assert (i < fe1.dofs_per_quad,
- ExcInternalError());
-
- master_dof_list.push_back (index+i);
- if (check_master_dof_list (face_interpolation_matrix,
- master_dof_list)
- == true)
- ++dofs_added;
- else
- master_dof_list.pop_back ();
-
- ++i;
- }
- index += fe1.dofs_per_quad;
- }
-
- AssertDimension (index, fe1.dofs_per_face);
- AssertDimension (master_dof_list.size(), fe2.dofs_per_face);
-
- // finally copy the list into the mask
- std::fill (master_dof_mask.begin(), master_dof_mask.end(), false);
- for (std::vector<types::global_dof_index>::const_iterator i=master_dof_list.begin();
- i!=master_dof_list.end(); ++i)
- master_dof_mask[*i] = true;
- }
-
-
-
- /**
- * Make sure that the mask exists that determines which dofs will be
- * the masters on refined faces where an fe1 and a fe2 meet.
- */
- template <int dim, int spacedim>
- void
- ensure_existence_of_master_dof_mask (const FiniteElement<dim,spacedim> &fe1,
- const FiniteElement<dim,spacedim> &fe2,
- const FullMatrix<double> &face_interpolation_matrix,
- std_cxx1x::shared_ptr<std::vector<bool> > &master_dof_mask)
- {
- if (master_dof_mask == std_cxx1x::shared_ptr<std::vector<bool> >())
- {
- master_dof_mask = std_cxx1x::shared_ptr<std::vector<bool> >
- (new std::vector<bool> (fe1.dofs_per_face));
- select_master_dofs_for_face_restriction (fe1,
- fe2,
- face_interpolation_matrix,
- *master_dof_mask);
- }
- }
-
-
-
- /**
- * Make sure that the given @p face_interpolation_matrix pointer
- * points to a valid matrix. If the pointer is zero beforehand,
- * create an entry with the correct data. If it is nonzero, don't
- * touch it.
- */
- template <int dim, int spacedim>
- void
- ensure_existence_of_face_matrix (const FiniteElement<dim,spacedim> &fe1,
- const FiniteElement<dim,spacedim> &fe2,
- std_cxx1x::shared_ptr<FullMatrix<double> > &matrix)
- {
- if (matrix == std_cxx1x::shared_ptr<FullMatrix<double> >())
- {
- matrix = std_cxx1x::shared_ptr<FullMatrix<double> >
- (new FullMatrix<double> (fe2.dofs_per_face,
- fe1.dofs_per_face));
- fe1.get_face_interpolation_matrix (fe2,
- *matrix);
- }
- }
-
-
-
- /**
- * Same, but for subface interpolation matrices.
- */
- template <int dim, int spacedim>
- void
- ensure_existence_of_subface_matrix (const FiniteElement<dim,spacedim> &fe1,
- const FiniteElement<dim,spacedim> &fe2,
- const unsigned int subface,
- std_cxx1x::shared_ptr<FullMatrix<double> > &matrix)
- {
- if (matrix == std_cxx1x::shared_ptr<FullMatrix<double> >())
- {
- matrix = std_cxx1x::shared_ptr<FullMatrix<double> >
- (new FullMatrix<double> (fe2.dofs_per_face,
- fe1.dofs_per_face));
- fe1.get_subface_interpolation_matrix (fe2,
- subface,
- *matrix);
- }
- }
-
-
-
- /**
- * Given the face interpolation matrix between two elements, split it
- * into its master and slave parts and invert the master part as
- * explained in the @ref hp_paper "hp paper".
- */
- void
- ensure_existence_of_split_face_matrix (const FullMatrix<double> &face_interpolation_matrix,
- const std::vector<bool> &master_dof_mask,
- std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > > &split_matrix)
- {
- AssertDimension (master_dof_mask.size(), face_interpolation_matrix.m());
- Assert (std::count (master_dof_mask.begin(), master_dof_mask.end(), true) ==
- static_cast<signed int>(face_interpolation_matrix.n()),
- ExcInternalError());
-
- if (split_matrix ==
- std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > >())
- {
- split_matrix
- = std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > >
- (new std::pair<FullMatrix<double>,FullMatrix<double> >());
-
- const unsigned int n_master_dofs = face_interpolation_matrix.n();
- const unsigned int n_dofs = face_interpolation_matrix.m();
-
- Assert (n_master_dofs <= n_dofs, ExcInternalError());
-
- // copy and invert the master
- // component, copy the slave
- // component
- split_matrix->first.reinit (n_master_dofs, n_master_dofs);
- split_matrix->second.reinit (n_dofs-n_master_dofs, n_master_dofs);
-
- unsigned int nth_master_dof = 0,
- nth_slave_dof = 0;
-
- for (unsigned int i=0; i<n_dofs; ++i)
- if (master_dof_mask[i] == true)
- {
- for (unsigned int j=0; j<n_master_dofs; ++j)
- split_matrix->first(nth_master_dof,j)
- = face_interpolation_matrix(i,j);
- ++nth_master_dof;
- }
- else
- {
- for (unsigned int j=0; j<n_master_dofs; ++j)
- split_matrix->second(nth_slave_dof,j)
- = face_interpolation_matrix(i,j);
- ++nth_slave_dof;
- }
-
- AssertDimension (nth_master_dof, n_master_dofs);
- AssertDimension (nth_slave_dof, n_dofs-n_master_dofs);
-
- //TODO[WB]: We should make sure very small entries are removed after inversion
- split_matrix->first.gauss_jordan ();
- }
- }
-
-
- // a template that can determine statically whether a given
- // DoFHandler class supports different finite element elements
- template <typename>
- struct DoFHandlerSupportsDifferentFEs
- {
- static const bool value = true;
- };
-
-
- template <int dim, int spacedim>
- struct DoFHandlerSupportsDifferentFEs< dealii::DoFHandler<dim,spacedim> >
- {
- static const bool value = false;
- };
-
-
- template <int dim, int spacedim>
- struct DoFHandlerSupportsDifferentFEs< dealii::MGDoFHandler<dim,spacedim> >
- {
- static const bool value = false;
- };
-
-
- /**
- * A function that returns how many different finite elements a dof
- * handler uses. This is one for non-hp DoFHandlers and
- * dof_handler.get_fe().size() for the hp-versions.
- */
- template <int dim, int spacedim>
- unsigned int
- n_finite_elements (const dealii::hp::DoFHandler<dim,spacedim> &dof_handler)
- {
- return dof_handler.get_fe().size();
- }
-
-
- template <class DH>
- unsigned int
- n_finite_elements (const DH &)
- {
- return 1;
- }
-
-
- /**
- * For a given face belonging to an active cell that borders to a
- * more refined cell, return the fe_index of the most dominating
- * finite element used on any of the face's subfaces.
- */
- template <typename face_iterator>
- unsigned int
- get_most_dominating_subface_fe_index (const face_iterator &face)
- {
- const unsigned int dim
- = face_iterator::AccessorType::dimension;
- const unsigned int spacedim
- = face_iterator::AccessorType::space_dimension;
-
- unsigned int dominating_subface_no = 0;
- for (; dominating_subface_no<face->n_children();
- ++dominating_subface_no)
- {
- // each of the subfaces can have only a single fe_index
- // associated with them, since there is no cell on the other
- // side
- Assert (face->child(dominating_subface_no)
- ->n_active_fe_indices()
- == 1,
- ExcInternalError());
-
- const FiniteElement<dim,spacedim> &
- this_subface_fe = (face->child(dominating_subface_no)
- ->get_fe (face->child(dominating_subface_no)
- ->nth_active_fe_index(0)));
-
- FiniteElementDomination::Domination
- domination = FiniteElementDomination::either_element_can_dominate;
- for (unsigned int sf=0; sf<face->n_children(); ++sf)
- if (sf != dominating_subface_no)
- {
- const FiniteElement<dim,spacedim> &
- that_subface_fe = (face->child(sf)
- ->get_fe (face->child(sf)
- ->nth_active_fe_index(0)));
-
- domination = domination &
- this_subface_fe.compare_for_face_domination(that_subface_fe);
- }
-
- // see if the element on this subface is able to dominate the
- // ones on all other subfaces, and if so take it
- if ((domination == FiniteElementDomination::this_element_dominates)
- ||
- (domination == FiniteElementDomination::either_element_can_dominate))
- break;
- }
-
- // check that we have found one such subface
- Assert (dominating_subface_no < face->n_children(),
- ExcNotImplemented());
-
- // return the finite element index used on it. note that only a
- // single fe can be active on such subfaces
- return face->child (dominating_subface_no)->nth_active_fe_index(0);
- }
-
-
-
- /**
- * Copy constraints into a constraint matrix object.
- *
- * This function removes zero constraints and those, which constrain
- * a DoF which was already eliminated in one of the previous steps of
- * the hp hanging node procedure.
- *
- * It also suppresses very small entries in the constraint matrix to
- * avoid making the sparsity pattern fuller than necessary.
- */
- void
- filter_constraints (const std::vector<types::global_dof_index> &master_dofs,
- const std::vector<types::global_dof_index> &slave_dofs,
- const FullMatrix<double> &face_constraints,
- ConstraintMatrix &constraints)
- {
- Assert (face_constraints.n () == master_dofs.size (),
- ExcDimensionMismatch(master_dofs.size (),
- face_constraints.n()));
- Assert (face_constraints.m () == slave_dofs.size (),
- ExcDimensionMismatch(slave_dofs.size (),
- face_constraints.m()));
-
- const unsigned int n_master_dofs = master_dofs.size ();
- const unsigned int n_slave_dofs = slave_dofs.size ();
-
- // check for a couple conditions that happened in parallel
- // distributed mode
- for (unsigned int row=0; row!=n_slave_dofs; ++row)
- Assert (slave_dofs[row] != numbers::invalid_dof_index,
- ExcInternalError());
- for (unsigned int col=0; col!=n_master_dofs; ++col)
- Assert (master_dofs[col] != numbers::invalid_dof_index,
- ExcInternalError());
-
-
- for (unsigned int row=0; row!=n_slave_dofs; ++row)
- if (constraints.is_constrained (slave_dofs[row]) == false)
- {
- bool constraint_already_satisfied = false;
-
- // Check if we have an identity constraint, which is already
- // satisfied by unification of the corresponding global dof
- // indices
- for (unsigned int i=0; i<n_master_dofs; ++i)
- if (face_constraints (row,i) == 1.0)
- if (master_dofs[i] == slave_dofs[row])
- {
- constraint_already_satisfied = true;
- break;
- }
-
- if (constraint_already_satisfied == false)
- {
- // add up the absolute values of all constraints in this
- // line to get a measure of their absolute size
- double abs_sum = 0;
- for (unsigned int i=0; i<n_master_dofs; ++i)
- abs_sum += std::abs (face_constraints(row,i));
-
- // then enter those constraints that are larger than
- // 1e-14*abs_sum. everything else probably originated
- // from inexact inversion of matrices and similar
- // effects. having those constraints in here will only
- // lead to problems because it makes sparsity patterns
- // fuller than necessary without producing any
- // significant effect
- constraints.add_line (slave_dofs[row]);
- for (unsigned int i=0; i<n_master_dofs; ++i)
- if ((face_constraints(row,i) != 0)
- &&
- (std::fabs(face_constraints(row,i)) >= 1e-14*abs_sum))
- constraints.add_entry (slave_dofs[row],
- master_dofs[i],
- face_constraints (row,i));
- constraints.set_inhomogeneity (slave_dofs[row], 0.);
- }
- }
- }
-
- }
-
-
-
- void
- make_hp_hanging_node_constraints (const dealii::DoFHandler<1> &,
- ConstraintMatrix &)
- {
- // nothing to do for regular dof handlers in 1d
- }
-
-
-
- void
- make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1> &,
- ConstraintMatrix &,
- dealii::internal::int2type<1>)
- {
- // nothing to do for regular dof handlers in 1d
- }
-
-
- void
- make_hp_hanging_node_constraints (const dealii::MGDoFHandler<1> &,
- ConstraintMatrix &)
- {
- // nothing to do for regular dof handlers in 1d
- }
-
-
-
- void
- make_oldstyle_hanging_node_constraints (const dealii::MGDoFHandler<1> &,
- ConstraintMatrix &,
- dealii::internal::int2type<1>)
- {
- // nothing to do for regular dof handlers in 1d
- }
-
-
- void
- make_hp_hanging_node_constraints (const dealii::hp::DoFHandler<1> &/*dof_handler*/,
- ConstraintMatrix &/*constraints*/)
- {
- // we may have to compute constraints for vertices. gotta think about
- // that a bit more
-
- //TODO[WB]: think about what to do here...
- }
-
-
-
- void
- make_oldstyle_hanging_node_constraints (const dealii::hp::DoFHandler<1> &/*dof_handler*/,
- ConstraintMatrix &/*constraints*/,
- dealii::internal::int2type<1>)
- {
- // we may have to compute constraints for vertices. gotta think about
- // that a bit more
-
- //TODO[WB]: think about what to do here...
- }
-
-
- void
- make_hp_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
- ConstraintMatrix &)
- {
- // nothing to do for regular dof handlers in 1d
- }
-
-
-
- void
- make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
- ConstraintMatrix &,
- dealii::internal::int2type<1>)
- {
- // nothing to do for regular dof handlers in 1d
- }
-
-
- void
- make_hp_hanging_node_constraints (const dealii::DoFHandler<1,3> &,
- ConstraintMatrix &)
- {
- // nothing to do for regular dof handlers in 1d
- }
-
- void
- make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,3> &,
- ConstraintMatrix &,
- dealii::internal::int2type<1>)
- {
- // nothing to do for regular dof handlers in 1d
- }
-
-
-// currently not used but may be in the future:
-
-// void
-// make_hp_hanging_node_constraints (const dealii::MDoFHandler<1,2> &,
-// ConstraintMatrix &)
-// {
-// // nothing to do for regular
-// // dof handlers in 1d
-// }
-
-
-
-// void
-// make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
-// ConstraintMatrix &,
-// dealii::internal::int2type<1>)
-// {
-// // nothing to do for regular
-// // dof handlers in 1d
-// }
-
-
-// void
-// make_oldstyle_hanging_node_constraints (const dealii::hp::DoFHandler<1,2> &/*dof_handler*/,
-// ConstraintMatrix &/*constraints*/,
-// dealii::internal::int2type<1>)
-// {
-// // we may have to compute
-// // constraints for
-// // vertices. gotta think about
-// // that a bit more
-//
-// //TODO[WB]: think about what to do here...
-// }
-//#endif
-
-
-
- template <class DH>
- void
- make_oldstyle_hanging_node_constraints (const DH &dof_handler,
- ConstraintMatrix &constraints,
- dealii::internal::int2type<2>)
- {
- const unsigned int dim = 2;
-
- const unsigned int spacedim = DH::space_dimension;
-
- std::vector<types::global_dof_index> dofs_on_mother;
- std::vector<types::global_dof_index> dofs_on_children;
-
- // loop over all lines; only on lines there can be constraints. We do
- // so by looping over all active cells and checking whether any of
- // the faces are refined which can only be from the neighboring cell
- // because this one is active. In that case, the face is subject to
- // constraints
- //
- // note that even though we may visit a face twice if the neighboring
- // cells are equally refined, we can only visit each face with
- // hanging nodes once
- typename DH::active_cell_iterator cell = dof_handler.begin_active(),
- endc = dof_handler.end();
- for (; cell!=endc; ++cell)
- // artificial cells can at best neighbor ghost cells, but we're not
- // interested in these interfaces
- if (!cell->is_artificial ())
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->has_children())
- {
- // in any case, faces can have at most two active fe
- // indices, but here the face can have only one (namely the
- // same as that from the cell we're sitting on), and each
- // of the children can have only one as well. check this
- Assert (cell->face(face)->n_active_fe_indices() == 1,
- ExcInternalError());
- Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
- == true,
- ExcInternalError());
- for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
- if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
- Assert (cell->face(face)->child(c)->n_active_fe_indices() == 1,
- ExcInternalError());
-
- // right now, all that is implemented is the case that both
- // sides use the same fe
- for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
- if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
- Assert (cell->face(face)->child(c)
- ->fe_index_is_active(cell->active_fe_index()) == true,
- ExcNotImplemented());
-
- // ok, start up the work
- const FiniteElement<dim,spacedim> &fe = cell->get_fe();
- const unsigned int fe_index = cell->active_fe_index();
-
- const unsigned int
- n_dofs_on_mother = 2*fe.dofs_per_vertex + fe.dofs_per_line,
- n_dofs_on_children = fe.dofs_per_vertex + 2*fe.dofs_per_line;
-
- dofs_on_mother.resize (n_dofs_on_mother);
- dofs_on_children.resize (n_dofs_on_children);
-
- Assert(n_dofs_on_mother == fe.constraints().n(),
- ExcDimensionMismatch(n_dofs_on_mother,
- fe.constraints().n()));
- Assert(n_dofs_on_children == fe.constraints().m(),
- ExcDimensionMismatch(n_dofs_on_children,
- fe.constraints().m()));
-
- const typename DH::line_iterator this_face = cell->face(face);
-
- // fill the dofs indices. Use same enumeration scheme as in
- // @p{FiniteElement::constraints()}
- unsigned int next_index = 0;
- for (unsigned int vertex=0; vertex<2; ++vertex)
- for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
- dofs_on_mother[next_index++] = this_face->vertex_dof_index(vertex,dof,
- fe_index);
- for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
- dofs_on_mother[next_index++] = this_face->dof_index(dof, fe_index);
- AssertDimension (next_index, dofs_on_mother.size());
-
- next_index = 0;
- for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
- dofs_on_children[next_index++]
- = this_face->child(0)->vertex_dof_index(1,dof,fe_index);
- for (unsigned int child=0; child<2; ++child)
- for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
- dofs_on_children[next_index++]
- = this_face->child(child)->dof_index(dof, fe_index);
- AssertDimension (next_index, dofs_on_children.size());
-
- // for each row in the constraint matrix for this line:
- for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
- {
- constraints.add_line (dofs_on_children[row]);
- for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
- constraints.add_entry (dofs_on_children[row],
- dofs_on_mother[i],
- fe.constraints()(row,i));
-
- constraints.set_inhomogeneity (dofs_on_children[row], 0.);
- }
- }
- else
- {
- // this face has no children, but it could still be that it
- // is shared by two cells that use a different fe index.
- // check a couple of things, but ignore the case that the
- // neighbor is an artificial cell
- if (!cell->at_boundary(face) &&
- !cell->neighbor(face)->is_artificial())
- {
- Assert (cell->face(face)->n_active_fe_indices() == 1,
- ExcNotImplemented());
- Assert (cell->face(face)
- ->fe_index_is_active(cell->active_fe_index()) == true,
- ExcInternalError());
- }
- }
- }
-
-
-
- template <class DH>
- void
- make_oldstyle_hanging_node_constraints (const DH &dof_handler,
- ConstraintMatrix &constraints,
- dealii::internal::int2type<3>)
- {
- const unsigned int dim = 3;
-
- std::vector<types::global_dof_index> dofs_on_mother;
- std::vector<types::global_dof_index> dofs_on_children;
-
- // loop over all quads; only on quads there can be constraints. We do
- // so by looping over all active cells and checking whether any of
- // the faces are refined which can only be from the neighboring cell
- // because this one is active. In that case, the face is subject to
- // constraints
- //
- // note that even though we may visit a face twice if the neighboring
- // cells are equally refined, we can only visit each face with
- // hanging nodes once
- typename DH::active_cell_iterator cell = dof_handler.begin_active(),
- endc = dof_handler.end();
- for (; cell!=endc; ++cell)
- // artificial cells can at best neighbor ghost cells, but we're not
- // interested in these interfaces
- if (!cell->is_artificial ())
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->has_children())
- {
- // first of all, make sure that we treat a case which is
- // possible, i.e. either no dofs on the face at all or no
- // anisotropic refinement
- if (cell->get_fe().dofs_per_face == 0)
- continue;
-
- Assert(cell->face(face)->refinement_case()==RefinementCase<dim-1>::isotropic_refinement,
- ExcNotImplemented());
-
- // in any case, faces can have at most two active fe
- // indices, but here the face can have only one (namely the
- // same as that from the cell we're sitting on), and each
- // of the children can have only one as well. check this
- AssertDimension (cell->face(face)->n_active_fe_indices(), 1);
- Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
- == true,
- ExcInternalError());
- for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
- AssertDimension (cell->face(face)->child(c)->n_active_fe_indices(), 1);
-
- // right now, all that is implemented is the case that both
- // sides use the same fe, and not only that but also that
- // all lines bounding this face and the children have the
- // same fe
- for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
- if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
- {
- Assert (cell->face(face)->child(c)
- ->fe_index_is_active(cell->active_fe_index()) == true,
- ExcNotImplemented());
- for (unsigned int e=0; e<4; ++e)
- {
- Assert (cell->face(face)->child(c)->line(e)
- ->n_active_fe_indices() == 1,
- ExcNotImplemented());
- Assert (cell->face(face)->child(c)->line(e)
- ->fe_index_is_active(cell->active_fe_index()) == true,
- ExcNotImplemented());
- }
- }
- for (unsigned int e=0; e<4; ++e)
- {
- Assert (cell->face(face)->line(e)
- ->n_active_fe_indices() == 1,
- ExcNotImplemented());
- Assert (cell->face(face)->line(e)
- ->fe_index_is_active(cell->active_fe_index()) == true,
- ExcNotImplemented());
- }
-
- // ok, start up the work
- const FiniteElement<dim> &fe = cell->get_fe();
- const unsigned int fe_index = cell->active_fe_index();
-
- const unsigned int n_dofs_on_mother = fe.dofs_per_face;
- const unsigned int n_dofs_on_children = (5*fe.dofs_per_vertex+
- 12*fe.dofs_per_line+
- 4*fe.dofs_per_quad);
-
- //TODO[TL]: think about this and the following in case of anisotropic refinement
-
- dofs_on_mother.resize (n_dofs_on_mother);
- dofs_on_children.resize (n_dofs_on_children);
-
- Assert(n_dofs_on_mother == fe.constraints().n(),
- ExcDimensionMismatch(n_dofs_on_mother,
- fe.constraints().n()));
- Assert(n_dofs_on_children == fe.constraints().m(),
- ExcDimensionMismatch(n_dofs_on_children,
- fe.constraints().m()));
-
- const typename DH::face_iterator this_face = cell->face(face);
-
- // fill the dofs indices. Use same enumeration scheme as in
- // @p{FiniteElement::constraints()}
- unsigned int next_index = 0;
- for (unsigned int vertex=0; vertex<4; ++vertex)
- for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
- dofs_on_mother[next_index++] = this_face->vertex_dof_index(vertex,dof,
- fe_index);
- for (unsigned int line=0; line<4; ++line)
- for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
- dofs_on_mother[next_index++]
- = this_face->line(line)->dof_index(dof, fe_index);
- for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
- dofs_on_mother[next_index++] = this_face->dof_index(dof, fe_index);
- AssertDimension (next_index, dofs_on_mother.size());
-
- next_index = 0;
-
- // assert some consistency assumptions
-
- //TODO[TL]: think about this in case of anisotropic
- //refinement
-
- Assert (dof_handler.get_tria().get_anisotropic_refinement_flag() ||
- ((this_face->child(0)->vertex_index(3) ==
- this_face->child(1)->vertex_index(2)) &&
- (this_face->child(0)->vertex_index(3) ==
- this_face->child(2)->vertex_index(1)) &&
- (this_face->child(0)->vertex_index(3) ==
- this_face->child(3)->vertex_index(0))),
- ExcInternalError());
- for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
- dofs_on_children[next_index++]
- = this_face->child(0)->vertex_dof_index(3,dof);
-
- // dof numbers on the centers of the lines bounding this
- // face
- for (unsigned int line=0; line<4; ++line)
- for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
- dofs_on_children[next_index++]
- = this_face->line(line)->child(0)->vertex_dof_index(1,dof, fe_index);
-
- // next the dofs on the lines interior to the face; the
- // order of these lines is laid down in the FiniteElement
- // class documentation
- for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
- dofs_on_children[next_index++]
- = this_face->child(0)->line(1)->dof_index(dof, fe_index);
- for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
- dofs_on_children[next_index++]
- = this_face->child(2)->line(1)->dof_index(dof, fe_index);
- for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
- dofs_on_children[next_index++]
- = this_face->child(0)->line(3)->dof_index(dof, fe_index);
- for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
- dofs_on_children[next_index++]
- = this_face->child(1)->line(3)->dof_index(dof, fe_index);
-
- // dofs on the bordering lines
- for (unsigned int line=0; line<4; ++line)
- for (unsigned int child=0; child<2; ++child)
- for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
- dofs_on_children[next_index++]
- = this_face->line(line)->child(child)->dof_index(dof, fe_index);
-
- // finally, for the dofs interior to the four child faces
- for (unsigned int child=0; child<4; ++child)
- for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
- dofs_on_children[next_index++]
- = this_face->child(child)->dof_index(dof, fe_index);
- AssertDimension (next_index, dofs_on_children.size());
-
- // for each row in the constraint matrix for this line:
- for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
- {
- constraints.add_line (dofs_on_children[row]);
- for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
- constraints.add_entry (dofs_on_children[row],
- dofs_on_mother[i],
- fe.constraints()(row,i));
-
- constraints.set_inhomogeneity(dofs_on_children[row], 0.);
- }
- }
- else
- {
- // this face has no children, but it could still be that it
- // is shared by two cells that use a different fe index.
- // check a couple of things, but ignore the case that the
- // neighbor is an artificial cell
- if (!cell->at_boundary(face) &&
- !cell->neighbor(face)->is_artificial())
- {
- Assert (cell->face(face)->n_active_fe_indices() == 1,
- ExcNotImplemented());
- Assert (cell->face(face)
- ->fe_index_is_active(cell->active_fe_index()) == true,
- ExcInternalError());
- }
- }
- }
-
-
- template <class DH>
- void
- make_hp_hanging_node_constraints (const DH &dof_handler,
- ConstraintMatrix &constraints)
- {
- // note: this function is going to be hard to understand if you
- // haven't read the hp paper. however, we try to follow the notation
- // laid out there, so go read the paper before you try to understand
- // what is going on here
-
- const unsigned int dim = DH::dimension;
-
- const unsigned int spacedim = DH::space_dimension;
-
-
- // a matrix to be used for constraints below. declared here and
- // simply resized down below to avoid permanent re-allocation of
- // memory
- FullMatrix<double> constraint_matrix;
-
- // similarly have arrays that will hold master and slave dof numbers,
- // as well as a scratch array needed for the complicated case below
- std::vector<types::global_dof_index> master_dofs;
- std::vector<types::global_dof_index> slave_dofs;
- std::vector<types::global_dof_index> scratch_dofs;
-
- // caches for the face and subface interpolation matrices between
- // different (or the same) finite elements. we compute them only
- // once, namely the first time they are needed, and then just reuse
- // them
- Table<2,std_cxx1x::shared_ptr<FullMatrix<double> > >
- face_interpolation_matrices (n_finite_elements (dof_handler),
- n_finite_elements (dof_handler));
- Table<3,std_cxx1x::shared_ptr<FullMatrix<double> > >
- subface_interpolation_matrices (n_finite_elements (dof_handler),
- n_finite_elements (dof_handler),
- GeometryInfo<dim>::max_children_per_face);
-
- // similarly have a cache for the matrices that are split into their
- // master and slave parts, and for which the master part is inverted.
- // these two matrices are derived from the face interpolation matrix
- // as described in the @ref hp_paper "hp paper"
- Table<2,std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > > >
- split_face_interpolation_matrices (n_finite_elements (dof_handler),
- n_finite_elements (dof_handler));
-
- // finally, for each pair of finite elements, have a mask that states
- // which of the degrees of freedom on the coarse side of a refined
- // face will act as master dofs.
- Table<2,std_cxx1x::shared_ptr<std::vector<bool> > >
- master_dof_masks (n_finite_elements (dof_handler),
- n_finite_elements (dof_handler));
-
- // loop over all faces
- //
- // note that even though we may visit a face twice if the neighboring
- // cells are equally refined, we can only visit each face with
- // hanging nodes once
- typename DH::active_cell_iterator cell = dof_handler.begin_active(),
- endc = dof_handler.end();
- for (; cell!=endc; ++cell)
- // artificial cells can at best neighbor ghost cells, but we're not
- // interested in these interfaces
- if (!cell->is_artificial ())
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->has_children())
- {
- // first of all, make sure that we treat a case which is
- // possible, i.e. either no dofs on the face at all or no
- // anisotropic refinement
- if (cell->get_fe().dofs_per_face == 0)
- continue;
-
- Assert(cell->face(face)->refinement_case()==RefinementCase<dim-1>::isotropic_refinement,
- ExcNotImplemented());
-
- // so now we've found a face of an active cell that has
- // children. that means that there are hanging nodes here.
-
- // in any case, faces can have at most two sets of active
- // fe indices, but here the face can have only one (namely
- // the same as that from the cell we're sitting on), and
- // each of the children can have only one as well. check
- // this
- Assert (cell->face(face)->n_active_fe_indices() == 1,
- ExcInternalError());
- Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
- == true,
- ExcInternalError());
- for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
- Assert (cell->face(face)->child(c)->n_active_fe_indices() == 1,
- ExcInternalError());
-
- // first find out whether we can constrain each of the
- // subfaces to the mother face. in the lingo of the hp
- // paper, this would be the simple case. note that we can
- // short-circuit this decision if the dof_handler doesn't
- // support hp at all
- //
- // ignore all interfaces with artificial cells
- FiniteElementDomination::Domination
- mother_face_dominates = FiniteElementDomination::either_element_can_dominate;
-
- if (DoFHandlerSupportsDifferentFEs<DH>::value == true)
- for (unsigned int c=0; c<cell->face(face)->number_of_children(); ++c)
- if (!cell->neighbor_child_on_subface (face, c)->is_artificial())
- mother_face_dominates = mother_face_dominates &
- (cell->get_fe().compare_for_face_domination
- (cell->neighbor_child_on_subface (face, c)->get_fe()));
-
- switch (mother_face_dominates)
- {
- case FiniteElementDomination::this_element_dominates:
- case FiniteElementDomination::either_element_can_dominate:
- {
- // Case 1 (the simple case and the only case that can
- // happen for non-hp DoFHandlers): The coarse element
- // dominates the elements on the subfaces (or they are
- // all the same)
- //
- // so we are going to constrain the DoFs on the face
- // children against the DoFs on the face itself
- master_dofs.resize (cell->get_fe().dofs_per_face);
-
- cell->face(face)->get_dof_indices (master_dofs,
- cell->active_fe_index ());
-
- // Now create constraint matrix for the subfaces and
- // assemble it. ignore all interfaces with artificial
- // cells because we can only get to such interfaces if
- // the current cell is a ghost cell
- for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
- {
- if (cell->neighbor_child_on_subface (face, c)->is_artificial())
- continue;
-
- const typename DH::active_face_iterator
- subface = cell->face(face)->child(c);
-
- Assert (subface->n_active_fe_indices() == 1,
- ExcInternalError());
-
- const unsigned int
- subface_fe_index = subface->nth_active_fe_index(0);
-
- // we sometime run into the situation where for
- // example on one big cell we have a FE_Q(1) and on
- // the subfaces we have a mixture of FE_Q(1) and
- // FE_Nothing. In that case, the face domination is
- // either_element_can_dominate for the whole
- // collection of subfaces, but on the particular
- // subface between FE_Q(1) and FE_Nothing, there
- // are no constraints that we need to take care of.
- // in that case, just continue
- if (cell->get_fe().compare_for_face_domination
- (subface->get_fe(subface_fe_index))
- ==
- FiniteElementDomination::no_requirements)
- continue;
-
- // Same procedure as for the mother cell. Extract
- // the face DoFs from the cell DoFs.
- slave_dofs.resize (subface->get_fe(subface_fe_index)
- .dofs_per_face);
- subface->get_dof_indices (slave_dofs, subface_fe_index);
-
- for (unsigned int i=0; i<slave_dofs.size(); ++i)
- Assert (slave_dofs[i] != numbers::invalid_dof_index,
- ExcInternalError());
-
- // Now create the element constraint for this
- // subface.
- //
- // As a side remark, one may wonder the following:
- // neighbor_child is clearly computed correctly,
- // i.e. taking into account face_orientation (just
- // look at the implementation of that function).
- // however, we don't care about this here, when we
- // ask for subface_interpolation on subface c. the
- // question rather is: do we have to translate 'c'
- // here as well?
- //
- // the answer is in fact 'no'. if one does that,
- // results are wrong: constraints are added twice
- // for the same pair of nodes but with differing
- // weights. in addition, one can look at the
- // deal.II/project_*_03 tests that look at exactly
- // this case: there, we have a mesh with at least
- // one face_orientation==false and hanging nodes,
- // and the results of those tests show that the
- // result of projection verifies the approximation
- // properties of a finite element onto that mesh
- ensure_existence_of_subface_matrix
- (cell->get_fe(),
- subface->get_fe(subface_fe_index),
- c,
- subface_interpolation_matrices
- [cell->active_fe_index()][subface_fe_index][c]);
-
- // Add constraints to global constraint matrix.
- filter_constraints (master_dofs,
- slave_dofs,
- *(subface_interpolation_matrices
- [cell->active_fe_index()][subface_fe_index][c]),
- constraints);
- }
-
- break;
- }
-
- case FiniteElementDomination::other_element_dominates:
- case FiniteElementDomination::neither_element_dominates:
- {
- // Case 2 (the "complex" case): at least one (the
- // neither_... case) of the finer elements or all of
- // them (the other_... case) is dominating. See the hp
- // paper for a way how to deal with this situation
- //
- // since this is something that can only happen for hp
- // dof handlers, add a check here...
- Assert (DoFHandlerSupportsDifferentFEs<DH>::value == true,
- ExcInternalError());
-
- // we first have to find the finite element that is
- // able to generate a space that all the other ones can
- // be constrained to
- const unsigned int dominating_fe_index
- = get_most_dominating_subface_fe_index (cell->face(face));
-
- const FiniteElement<dim,spacedim> &dominating_fe
- = dof_handler.get_fe()[dominating_fe_index];
-
- // check also that it is able to constrain the mother
- // face. it should be, or we wouldn't have gotten into
- // the branch for the 'complex' case
- Assert ((dominating_fe.compare_for_face_domination
- (cell->face(face)->get_fe(cell->face(face)->nth_active_fe_index(0)))
- == FiniteElementDomination::this_element_dominates)
- ||
- (dominating_fe.compare_for_face_domination
- (cell->face(face)->get_fe(cell->face(face)->nth_active_fe_index(0)))
- == FiniteElementDomination::either_element_can_dominate),
- ExcInternalError());
-
-
- // first get the interpolation matrix from the mother
- // to the virtual dofs
- Assert (dominating_fe.dofs_per_face <=
- cell->get_fe().dofs_per_face,
- ExcInternalError());
-
- ensure_existence_of_face_matrix
- (dominating_fe,
- cell->get_fe(),
- face_interpolation_matrices
- [dominating_fe_index][cell->active_fe_index()]);
-
- // split this matrix into master and slave components.
- // invert the master component
- ensure_existence_of_master_dof_mask
- (cell->get_fe(),
- dominating_fe,
- (*face_interpolation_matrices
- [dominating_fe_index]
- [cell->active_fe_index()]),
- master_dof_masks
- [dominating_fe_index]
- [cell->active_fe_index()]);
-
- ensure_existence_of_split_face_matrix
- (*face_interpolation_matrices
- [dominating_fe_index][cell->active_fe_index()],
- (*master_dof_masks
- [dominating_fe_index][cell->active_fe_index()]),
- split_face_interpolation_matrices
- [dominating_fe_index][cell->active_fe_index()]);
-
- const FullMatrix<double> &restrict_mother_to_virtual_master_inv
- = (split_face_interpolation_matrices
- [dominating_fe_index][cell->active_fe_index()]->first);
-
- const FullMatrix<double> &restrict_mother_to_virtual_slave
- = (split_face_interpolation_matrices
- [dominating_fe_index][cell->active_fe_index()]->second);
-
- // now compute the constraint matrix as the product
- // between the inverse matrix and the slave part
- constraint_matrix.reinit (cell->get_fe().dofs_per_face -
- dominating_fe.dofs_per_face,
- dominating_fe.dofs_per_face);
- restrict_mother_to_virtual_slave
- .mmult (constraint_matrix,
- restrict_mother_to_virtual_master_inv);
-
- // then figure out the global numbers of master and
- // slave dofs and apply constraints
- scratch_dofs.resize (cell->get_fe().dofs_per_face);
- cell->face(face)->get_dof_indices (scratch_dofs,
- cell->active_fe_index ());
-
- // split dofs into master and slave components
- master_dofs.clear ();
- slave_dofs.clear ();
- for (unsigned int i=0; i<cell->get_fe().dofs_per_face; ++i)
- if ((*master_dof_masks
- [dominating_fe_index][cell->active_fe_index()])[i] == true)
- master_dofs.push_back (scratch_dofs[i]);
- else
- slave_dofs.push_back (scratch_dofs[i]);
-
- AssertDimension (master_dofs.size(), dominating_fe.dofs_per_face);
- AssertDimension (slave_dofs.size(),
- cell->get_fe().dofs_per_face - dominating_fe.dofs_per_face);
-
- filter_constraints (master_dofs,
- slave_dofs,
- constraint_matrix,
- constraints);
-
-
-
- // next we have to deal with the subfaces. do as
- // discussed in the hp paper
- for (unsigned int sf=0;
- sf<cell->face(face)->n_children(); ++sf)
- {
- // ignore interfaces with artificial cells as well
- // as interfaces between ghost cells in 2d
- if (cell->neighbor_child_on_subface (face, sf)->is_artificial()
- ||
- (dim==2 && cell->is_ghost()
- &&
- cell->neighbor_child_on_subface (face, sf)->is_ghost()))
- continue;
-
- Assert (cell->face(face)->child(sf)
- ->n_active_fe_indices() == 1,
- ExcInternalError());
-
- const unsigned int subface_fe_index
- = cell->face(face)->child(sf)->nth_active_fe_index(0);
- const FiniteElement<dim,spacedim> &subface_fe
- = dof_handler.get_fe()[subface_fe_index];
-
- // first get the interpolation matrix from the
- // subface to the virtual dofs
- Assert (dominating_fe.dofs_per_face <=
- subface_fe.dofs_per_face,
- ExcInternalError());
- ensure_existence_of_subface_matrix
- (dominating_fe,
- subface_fe,
- sf,
- subface_interpolation_matrices
- [dominating_fe_index][subface_fe_index][sf]);
-
- const FullMatrix<double> &restrict_subface_to_virtual
- = *(subface_interpolation_matrices
- [dominating_fe_index][subface_fe_index][sf]);
-
- constraint_matrix.reinit (subface_fe.dofs_per_face,
- dominating_fe.dofs_per_face);
-
- restrict_subface_to_virtual
- .mmult (constraint_matrix,
- restrict_mother_to_virtual_master_inv);
-
- slave_dofs.resize (subface_fe.dofs_per_face);
- cell->face(face)->child(sf)->get_dof_indices (slave_dofs,
- subface_fe_index);
-
- filter_constraints (master_dofs,
- slave_dofs,
- constraint_matrix,
- constraints);
- }
-
- break;
- }
-
- case FiniteElementDomination::no_requirements:
- // there are no continuity requirements between the two
- // elements. record no constraints
- break;
-
- default:
- // we shouldn't get here
- Assert (false, ExcInternalError());
- }
- }
- else
- {
- // this face has no children, but it could still be that it
- // is shared by two cells that use a different fe index
- Assert (cell->face(face)
- ->fe_index_is_active(cell->active_fe_index()) == true,
- ExcInternalError());
-
- // see if there is a neighbor that is an artificial cell.
- // in that case, we're not interested in this interface. we
- // test this case first since artificial cells may not have
- // an active_fe_index set, etc
- if (!cell->at_boundary(face)
- &&
- cell->neighbor(face)->is_artificial())
- continue;
-
- // Only if there is a neighbor with a different
- // active_fe_index and the same h-level, some action has to
- // be taken.
- if ((DoFHandlerSupportsDifferentFEs<DH>::value == true)
- &&
- !cell->face(face)->at_boundary ()
- &&
- (cell->neighbor(face)->active_fe_index () !=
- cell->active_fe_index ())
- &&
- (!cell->face(face)->has_children() &&
- !cell->neighbor_is_coarser(face) ))
- {
- const typename DH::level_cell_iterator neighbor = cell->neighbor (face);
-
- // see which side of the face we have to constrain
- switch (cell->get_fe().compare_for_face_domination (neighbor->get_fe ()))
- {
- case FiniteElementDomination::this_element_dominates:
- {
- // Get DoFs on dominating and dominated side of the
- // face
- master_dofs.resize (cell->get_fe().dofs_per_face);
- cell->face(face)->get_dof_indices (master_dofs,
- cell->active_fe_index ());
-
- slave_dofs.resize (neighbor->get_fe().dofs_per_face);
- cell->face(face)->get_dof_indices (slave_dofs,
- neighbor->active_fe_index ());
-
- // break if the n_master_dofs == 0, because we are
- // attempting to constrain to an element that has
- // no face dofs
- if (master_dofs.size() == 0) break;
-
- // make sure the element constraints for this face
- // are available
- ensure_existence_of_face_matrix
- (cell->get_fe(),
- neighbor->get_fe(),
- face_interpolation_matrices
- [cell->active_fe_index()][neighbor->active_fe_index()]);
-
- // Add constraints to global constraint matrix.
- filter_constraints (master_dofs,
- slave_dofs,
- *(face_interpolation_matrices
- [cell->active_fe_index()]
- [neighbor->active_fe_index()]),
- constraints);
-
- break;
- }
-
- case FiniteElementDomination::other_element_dominates:
- {
- // we don't do anything here since we will come
- // back to this face from the other cell, at which
- // time we will fall into the first case clause
- // above
- break;
- }
-
- case FiniteElementDomination::either_element_can_dominate:
- {
- // it appears as if neither element has any
- // constraints on its neighbor. this may be because
- // neither element has any DoFs on faces at all. or
- // that the two elements are actually the same,
- // although they happen to run under different
- // fe_indices (this is what happens in
- // hp/hp_hanging_nodes_01 for example).
- //
- // another possibility is what happens in crash_13.
- // there, we have FESystem(FE_Q(1),FE_DGQ(0)) vs.
- // FESystem(FE_Q(1),FE_DGQ(1)). neither of them
- // 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;
- }
-
- case FiniteElementDomination::neither_element_dominates:
- {
- // we don't presently know what exactly to do here.
- // it isn't quite clear what exactly we would have
- // to do here. sit tight until someone trips over
- // the following statement and see what exactly is
- // going on
- Assert (false, ExcNotImplemented());
- break;
- }
-
- case FiniteElementDomination::no_requirements:
- {
- // nothing to do here
- break;
- }
-
- default:
- // we shouldn't get here
- Assert (false, ExcInternalError());
- }
- }
- }
- }
- }
-
-
-
-
- template <class DH>
- void
- make_hanging_node_constraints (const DH &dof_handler,
- ConstraintMatrix &constraints)
- {
- // Decide whether to use the new or old make_hanging_node_constraints
- // function. If all the FiniteElement or all elements in a FECollection
- // support the new face constraint matrix, the new code will be used.
- // Otherwise, the old implementation is used for the moment.
- if (dof_handler.get_fe().hp_constraints_are_implemented ())
- internal::
- make_hp_hanging_node_constraints (dof_handler,
- constraints);
- else
- internal::
- make_oldstyle_hanging_node_constraints (dof_handler,
- constraints,
- dealii::internal::int2type<DH::dimension>());
- }
-
-
-
- namespace
- {
- // enter constraints for periodicity into the given ConstraintMatrix object.
- // this function is called when at least one of the two face iterators corresponds
- // to an active object without further children
- //
- // @param transformation A matrix that maps degrees of freedom from one face
- // to another. If the DoFs on the two faces are supposed to match exactly, then
- // the matrix so provided will be the identity matrix. if face 2 is once refined
- // from face 1, then the matrix needs to be the interpolation matrix from a face
- // 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 <typename FaceIterator>
- void
- set_periodicity_constraints (const FaceIterator &face_1,
- const typename identity<FaceIterator>::type &face_2,
- const FullMatrix<double> &transformation,
- dealii::ConstraintMatrix &constraint_matrix,
- const ComponentMask &component_mask,
- const bool face_orientation,
- const bool face_flip,
- const bool face_rotation)
- {
- static const int dim = FaceIterator::AccessorType::dimension;
- static const int spacedim = FaceIterator::AccessorType::space_dimension;
-
- // we should be in the case where face_1 is active, i.e. has no children:
- Assert (!face_1->has_children(),
- ExcInternalError());
-
- Assert (face_1->n_active_fe_indices() == 1,
- ExcInternalError());
-
- // if face_2 does have children, then we need to iterate over them
- if (face_2->has_children())
- {
- Assert (face_2->n_children() == GeometryInfo<dim>::max_children_per_face,
- ExcNotImplemented());
- const unsigned int dofs_per_face
- = face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face;
- FullMatrix<double> child_transformation (dofs_per_face, dofs_per_face);
- FullMatrix<double> subface_interpolation (dofs_per_face, dofs_per_face);
- for (unsigned int c=0; c<face_2->n_children(); ++c)
- {
- // get the interpolation matrix recursively from the one that
- // interpolated from face_1 to face_2 by multiplying from the
- // left with the one that interpolates from face_2 to
- // its child
- face_1->get_fe(face_1->nth_active_fe_index(0))
- .get_subface_interpolation_matrix (face_1->get_fe(face_1->nth_active_fe_index(0)),
- c,
- subface_interpolation);
- subface_interpolation.mmult (child_transformation, transformation);
- set_periodicity_constraints(face_1, face_2->child(c),
- child_transformation,
- constraint_matrix, component_mask,
- face_orientation, face_flip, face_rotation);
- }
- }
- else
- // both faces are active. we need to match the corresponding DoFs of both faces
- {
- const unsigned int face_1_index = face_1->nth_active_fe_index(0);
- const unsigned int face_2_index = face_2->nth_active_fe_index(0);
- Assert(face_1->get_fe(face_1_index) == face_2->get_fe(face_1_index),
- ExcMessage ("Matching periodic cells need to use the same finite element"));
-
- const FiniteElement<dim, spacedim> &fe = face_1->get_fe(face_1_index);
-
- Assert(component_mask.represents_n_components(fe.n_components()),
- ExcMessage ("The number of components in the mask has to be either "
- "zero or equal to the number of components in the finite " "element."));
-
- const unsigned int dofs_per_face = fe.dofs_per_face;
-
- std::vector<types::global_dof_index> dofs_1(dofs_per_face);
- std::vector<types::global_dof_index> dofs_2(dofs_per_face);
-
- face_1->get_dof_indices(dofs_1, face_1_index);
- face_2->get_dof_indices(dofs_2, face_2_index);
-
- // Well, this is a hack:
- //
- // There is no
- // face_to_face_index(face_index,
- // face_orientation,
- // face_flip,
- // face_rotation)
- // function in FiniteElementData, so we have to use
- // face_to_cell_index(face_index, face
- // face_orientation,
- // face_flip,
- // face_rotation)
- // But this will give us an index on a cell - something we cannot work
- // with directly. But luckily we can match them back :-]
-
- std::map<unsigned int, unsigned int> cell_to_rotated_face_index;
-
- // Build up a cell to face index for face_2:
- for (unsigned int i = 0; i < dofs_per_face; ++i)
- {
- const unsigned int cell_index = fe.face_to_cell_index(i, 0, /* It doesn't really matter, just assume
- * we're on the first face...
- */
- true, false, false // default orientation
- );
- cell_to_rotated_face_index[cell_index] = i;
- }
-
- // loop over all dofs on face 2 and constrain them again the ones on face 1
- for (unsigned int i=0; i<dofs_per_face; ++i)
- if (!constraint_matrix.is_constrained(dofs_2[i]))
- if ((component_mask.n_selected_components(fe.n_components())
- == fe.n_components())
- ||
- component_mask[fe.face_system_to_component_index(i).first])
- {
- // 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<dofs_per_face; ++jj)
- if (((transformation(i,jj) == 0) || (transformation(i,jj) == 1)) == false)
- {
- is_identity_constrained = false;
- break;
- }
- unsigned int identity_constraint_target = numbers::invalid_unsigned_int;
- if (is_identity_constrained == true)
- {
- bool one_identity_found = false;
- for (unsigned int jj=0; jj<dofs_per_face; ++jj)
- if (transformation(i,jj) == 1)
- {
- if (one_identity_found == false)
- {
- one_identity_found = true;
- identity_constraint_target = jj;
- }
- else
- {
- is_identity_constrained = false;
- identity_constraint_target = numbers::invalid_unsigned_int;
- break;
- }
- }
- }
-
- // now treat constraints, either as an equality constraint or
- // as a sequence of constraints
- if (is_identity_constrained == true)
- {
- // Query the correct face_index on face_2 respecting the given
- // orientation:
- const unsigned int j =
- cell_to_rotated_face_index[fe.face_to_cell_index(identity_constraint_target,
- 0, /* It doesn't really matter, just assume
- * we're on the first face...
- */
- face_orientation, face_flip, face_rotation)];
-
- // if the two aren't already identity constrained (whichever way
- // around, then enter the constraint. otherwise there is nothing
- // for us still to do
- if (constraint_matrix.are_identity_constrained(dofs_2[i], dofs_1[i]) == false)
- {
- constraint_matrix.add_line(dofs_2[i]);
- constraint_matrix.add_entry(dofs_2[i], dofs_1[j], 1);
- }
- }
- else
- {
- // this is just a regular constraint. enter it piece by piece
- constraint_matrix.add_line(dofs_2[i]);
- for (unsigned int jj=0; jj<dofs_per_face; ++jj)
- {
- // Query the correct face_index on face_2 respecting the given
- // orientation:
- const unsigned int j =
- cell_to_rotated_face_index[fe.face_to_cell_index(jj, 0, /* It doesn't really matter, just assume
- * we're on the first face...
- */
- face_orientation, face_flip, face_rotation)];
-
- // And finally constrain the two DoFs respecting component_mask:
- if (transformation(i,jj) != 0)
- constraint_matrix.add_entry(dofs_2[i], dofs_1[j],
- transformation(i,jj));
- }
- }
- }
- }
- }
- }
-
-
- template <typename FaceIterator>
- void
- make_periodicity_constraints (const FaceIterator &face_1,
- const typename identity<FaceIterator>::type &face_2,
- dealii::ConstraintMatrix &constraint_matrix,
- const ComponentMask &component_mask,
- const bool face_orientation,
- const bool face_flip,
- const bool face_rotation)
- {
- static const int dim = FaceIterator::AccessorType::dimension;
-
- Assert( (dim != 1) ||
- (face_orientation == true &&
- face_flip == false &&
- face_rotation == false),
- ExcMessage ("The supplied orientation "
- "(face_orientation, face_flip, face_rotation) "
- "is invalid for 1D"));
-
- Assert( (dim != 2) ||
- (face_orientation == true &&
- face_rotation == false),
- ExcMessage ("The supplied orientation "
- "(face_orientation, face_flip, face_rotation) "
- "is invalid for 2D"));
-
- Assert(face_1 != face_2,
- ExcMessage ("face_1 and face_2 are equal! Cannot constrain DoFs "
- "on the very same face"));
-
- Assert(face_1->at_boundary() && face_2->at_boundary(),
- ExcMessage ("Faces for periodicity constraints must be on the boundary"));
-
-
- // A lookup table on how to go through the child faces depending on the
- // orientation:
-
- static const int lookup_table_2d[2][2] =
- {
- // flip:
- {0, 1}, // false
- {1, 0}, // true
- };
-
- static const int lookup_table_3d[2][2][2][4] =
- {
- // orientation flip rotation
- { { {0, 2, 1, 3}, // false false false
- {2, 3, 0, 1}, // false false true
- },
- { {3, 1, 2, 0}, // false true false
- {1, 0, 3, 2}, // false true true
- },
- },
- { { {0, 1, 2, 3}, // true false false
- {1, 3, 0, 2}, // true false true
- },
- { {3, 2, 1, 0}, // true true false
- {2, 0, 3, 1}, // true true true
- },
- },
- };
-
- // In the case that both faces have children, we loop over all
- // children and apply make_periodicty_constrains recursively:
- if (face_1->has_children() && face_2->has_children())
- {
- Assert(face_1->n_children() == GeometryInfo<dim>::max_children_per_face &&
- face_2->n_children() == GeometryInfo<dim>::max_children_per_face,
- ExcNotImplemented());
-
- for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face; ++i)
- {
- // Lookup the index for the second face
- unsigned int j;
- switch (dim)
- {
- case 2:
- j = lookup_table_2d[face_flip][i];
- break;
- case 3:
- j = lookup_table_3d[face_orientation][face_flip][face_rotation][i];
- break;
- default:
- AssertThrow(false, ExcNotImplemented());
- }
-
- make_periodicity_constraints (face_1->child(i),
- face_2->child(j),
- constraint_matrix,
- component_mask,
- face_orientation,
- face_flip,
- face_rotation);
- }
- }
- else
- // otherwise at least one of the two faces is active and
- // we need to enter the constraints
- {
- if (face_2->has_children() == false)
- set_periodicity_constraints(face_2, face_1,
- FullMatrix<double>(IdentityMatrix(face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face)),
- constraint_matrix,
- component_mask,
- face_orientation, face_flip, face_rotation);
- else
- set_periodicity_constraints(face_1, face_2,
- FullMatrix<double>(IdentityMatrix(face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face)),
- constraint_matrix,
- component_mask,
- face_orientation, face_flip, face_rotation);
- }
- }
-
-
-
- template<typename DH>
- void
- make_periodicity_constraints (const DH &dof_handler,
- const types::boundary_id b_id1,
- const types::boundary_id b_id2,
- const int direction,
- dealii::ConstraintMatrix &constraint_matrix,
- const ComponentMask &component_mask)
- {
- Tensor<1,DH::space_dimension> dummy;
- make_periodicity_constraints (dof_handler,
- b_id1,
- b_id2,
- direction,
- dummy,
- constraint_matrix,
- component_mask);
- }
-
-
-
- template<typename DH>
- void
- make_periodicity_constraints (const DH &dof_handler,
- const types::boundary_id b_id1,
- const types::boundary_id b_id2,
- const int direction,
- dealii::Tensor<1,DH::space_dimension> &offset,
- dealii::ConstraintMatrix &constraint_matrix,
- const ComponentMask &component_mask)
- {
- static const int space_dim = DH::space_dimension;
- Assert (0<=direction && direction<space_dim,
- ExcIndexRange (direction, 0, space_dim));
-
-#if defined(DEBUG) && defined(DEAL_II_WITH_P4EST)
- // Check whether we run on a non parallel mesh or on a
- // parallel::distributed::Triangulation in serial
- {
- typedef parallel::distributed::Triangulation<DH::dimension,DH::space_dimension> PTRIA;
- const PTRIA *ptria_p = dynamic_cast<const PTRIA *> (&dof_handler.get_tria());
- Assert ((ptria_p == 0 || Utilities::MPI::n_mpi_processes(ptria_p->get_communicator()) == 1),
- ExcMessage ("This function can not be used with distributed triangulations."
- "See the documentation for more information."));
- }
-#endif
-
- Assert (b_id1 != b_id2,
- ExcMessage ("The boundary indicators b_id1 and b_id2 must be"
- "different to denote different boundaries."));
-
- typedef typename DH::face_iterator FaceIterator;
- typedef std::map<FaceIterator, std::pair<FaceIterator, std::bitset<3> > > FaceMap;
-
- // Collect matching periodic cells on the coarsest level:
- FaceMap matched_cells =
- GridTools::collect_periodic_face_pairs(dof_handler,
- b_id1, b_id2,
- direction, offset);
-
- // And apply the low level make_periodicity_constraints function to
- // every matching pair:
- for (typename FaceMap::iterator it = matched_cells.begin();
- it != matched_cells.end(); ++it)
- {
- typedef typename DH::face_iterator FaceIterator;
- const FaceIterator &face_1 = it->first;
- const FaceIterator &face_2 = it->second.first;
- const std::bitset<3> &orientation = it->second.second;
-
- Assert(face_1->at_boundary() && face_2->at_boundary(),
- ExcInternalError());
-
- Assert (face_1->boundary_indicator() == b_id1 &&
- face_2->boundary_indicator() == b_id2,
- ExcInternalError());
-
- Assert (face_1 != face_2,
- ExcInternalError());
-
- make_periodicity_constraints(face_1,
- face_2,
- constraint_matrix,
- component_mask,
- orientation[0],
- orientation[1],
- orientation[2]);
- }
- }
-
-
-
- template<typename DH>
- void
- make_periodicity_constraints (const DH &dof_handler,
- const types::boundary_id b_id,
- const int direction,
- dealii::ConstraintMatrix &constraint_matrix,
- const ComponentMask &component_mask)
- {
- Tensor<1,DH::space_dimension> dummy;
- make_periodicity_constraints (dof_handler,
- b_id,
- direction,
- dummy,
- constraint_matrix,
- component_mask);
- }
-
-
-
- template<typename DH>
- void
- make_periodicity_constraints (const DH &dof_handler,
- const types::boundary_id b_id,
- const int direction,
- dealii::Tensor<1,DH::space_dimension> &offset,
- dealii::ConstraintMatrix &constraint_matrix,
- const ComponentMask &component_mask)
- {
- static const int dim = DH::dimension;
- static const int space_dim = DH::space_dimension;
-
- Assert (0<=direction && direction<space_dim,
- ExcIndexRange (direction, 0, space_dim));
-
- Assert(dim == space_dim,
- ExcNotImplemented());
-
-#if defined(DEBUG) && defined(DEAL_II_WITH_P4EST)
- // Check whether we run on a non parallel mesh or on a
- // parallel::distributed::Triangulation in serial
- {
- typedef typename parallel::distributed::Triangulation<DH::dimension,DH::space_dimension> PTRIA;
- const PTRIA *ptria_p = dynamic_cast<const PTRIA *> (&dof_handler.get_tria());
- Assert ((ptria_p == 0 || Utilities::MPI::n_mpi_processes(ptria_p->get_communicator()) == 1),
- ExcMessage ("This function can not be used with distributed triangulations."
- "See the documentation for more information."));
- }
-#endif
-
- typedef typename DH::face_iterator FaceIterator;
- typedef std::map<FaceIterator, FaceIterator> FaceMap;
-
- // Collect matching periodic cells on the coarsest level:
- FaceMap matched_cells =
- GridTools::collect_periodic_face_pairs(dof_handler,
- b_id,
- direction, offset);
-
- // And apply the low level make_periodicity_constraints function to
- // every matching pair:
- for (typename FaceMap::iterator it = matched_cells.begin();
- it != matched_cells.end(); ++it)
- {
- typedef typename DH::face_iterator FaceIterator;
- const FaceIterator &face_1 = it->first;
- const FaceIterator &face_2 = it->second;
-
- Assert(face_1->at_boundary() && face_2->at_boundary(),
- ExcInternalError());
-
- Assert (face_1->boundary_indicator() == b_id &&
- face_2->boundary_indicator() == b_id,
- ExcInternalError());
-
- Assert (face_1 != face_2,
- ExcInternalError());
-
- make_periodicity_constraints(face_1,
- face_2,
- constraint_matrix,
- component_mask
- /* standard orientation */);
- }
- }
-
-
-
namespace internal
{
// return an array that for each dof on the reference cell
-
- namespace internal
- {
- namespace
- {
- /**
- * This is a function that is called by the _2 function and that
- * operates on a range of cells only. It is used to split up the
- * whole range of cells into chunks which are then worked on in
- * parallel, if multithreading is available.
- */
- template <int dim, int spacedim>
- void
- compute_intergrid_weights_3 (
- const dealii::DoFHandler<dim,spacedim> &coarse_grid,
- const unsigned int coarse_component,
- const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
- const std::vector<dealii::Vector<double> > ¶meter_dofs,
- const std::vector<types::global_dof_index> &weight_mapping,
- std::vector<std::map<types::global_dof_index, float> > &weights,
- const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &begin,
- const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &end)
- {
- // aliases to the finite elements used by the dof handlers:
- const FiniteElement<dim,spacedim> &coarse_fe = coarse_grid.get_fe();
-
- // for each cell on the parameter grid: find out which degrees of
- // freedom on the fine grid correspond in which way to the degrees
- // of freedom on the parameter grid
- //
- // since for continuous FEs some dofs exist on more than one cell,
- // we have to track which ones were already visited. the problem is
- // that if we visit a dof first on one cell and compute its weight
- // with respect to some global dofs to be non-zero, and later visit
- // the dof again on another cell and (since we are on another cell)
- // recompute the weights with respect to the same dofs as above to
- // be zero now, we have to preserve them. we therefore overwrite
- // all weights if they are nonzero and do not enforce zero weights
- // since that might be only due to the fact that we are on another
- // cell.
- //
- // example:
- // coarse grid
- // | | |
- // *-----*-----*
- // | cell|cell |
- // | 1 | 2 |
- // | | |
- // 0-----1-----*
- //
- // fine grid
- // | | | | |
- // *--*--*--*--*
- // | | | | |
- // *--*--*--*--*
- // | | | | |
- // *--x--y--*--*
- //
- // when on cell 1, we compute the weights of dof 'x' to be 1/2 from
- // parameter dofs 0 and 1, respectively. however, when later we are
- // on cell 2, we again compute the prolongation of shape function 1
- // restricted to cell 2 to the globla grid and find that the weight
- // of global dof 'x' now is zero. however, we should not overwrite
- // the old value.
- //
- // we therefore always only set nonzero values. why adding up is
- // not useful: dof 'y' would get weight 1 from parameter dof 1 on
- // both cells 1 and 2, but the correct weight is nevertheless only
- // 1.
-
- // vector to hold the representation of a single degree of freedom
- // on the coarse grid (for the selected fe) on the fine grid
- const types::global_dof_index n_fine_dofs = weight_mapping.size();
- dealii::Vector<double> global_parameter_representation (n_fine_dofs);
-
- typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator cell;
- std::vector<types::global_dof_index> parameter_dof_indices (coarse_fe.dofs_per_cell);
-
- for (cell=begin; cell!=end; ++cell)
- {
- // get the global indices of the parameter dofs on this
- // parameter grid cell
- cell->get_dof_indices (parameter_dof_indices);
-
- // loop over all dofs on this cell and check whether they are
- // interesting for us
- for (unsigned int local_dof=0;
- local_dof<coarse_fe.dofs_per_cell;
- ++local_dof)
- if (coarse_fe.system_to_component_index(local_dof).first
- ==
- coarse_component)
- {
- // the how-many-th parameter is this on this cell?
- const unsigned int local_parameter_dof
- = coarse_fe.system_to_component_index(local_dof).second;
-
- global_parameter_representation = 0;
-
- // distribute the representation of
- // @p{local_parameter_dof} on the parameter grid cell
- // @p{cell} to the global data space
- coarse_to_fine_grid_map[cell]->
- set_dof_values_by_interpolation (parameter_dofs[local_parameter_dof],
- global_parameter_representation);
- // now that we've got the global representation of each
- // parameter dof, we've only got to clobber the non-zero
- // entries in that vector and store the result
- //
- // what we have learned: if entry @p{i} of the global
- // vector holds the value @p{v[i]}, then this is the
- // weight with which the present dof contributes to
- // @p{i}. there may be several such @p{i}s and their
- // weights' sum should be one. Then, @p{v[i]} should be
- // equal to @p{\sum_j w_{ij} p[j]} with @p{p[j]} be the
- // values of the degrees of freedom on the coarse grid.
- // we can thus compute constraints which link the degrees
- // of freedom @p{v[i]} on the fine grid to those on the
- // coarse grid, @p{p[j]}. Now to use these as real
- // constraints, rather than as additional equations, we
- // have to identify representants among the @p{i} for
- // each @p{j}. this will be done by simply taking the
- // first @p{i} for which @p{w_{ij}==1}.
- //
- // guard modification of the weights array by a Mutex.
- // since it should happen rather rarely that there are
- // several threads operating on different intergrid
- // weights, have only one mutex for all of them
- static Threads::Mutex mutex;
- Threads::Mutex::ScopedLock lock (mutex);
- for (types::global_dof_index i=0; i<global_parameter_representation.size(); ++i)
- // set this weight if it belongs to a parameter dof.
- if (weight_mapping[i] != numbers::invalid_dof_index)
- {
- // only overwrite old value if not by zero
- if (global_parameter_representation(i) != 0)
- {
- const types::global_dof_index wi = parameter_dof_indices[local_dof],
- wj = weight_mapping[i];
- weights[wi][wj] = global_parameter_representation(i);
- };
- }
- else
- Assert (global_parameter_representation(i) == 0,
- ExcInternalError());
- }
- }
- }
-
-
- /**
- * This is a helper function that is used in the computation of
- * integrid constraints. See the function for a thorough description
- * of how it works.
- */
- template <int dim, int spacedim>
- void
- compute_intergrid_weights_2 (
- const dealii::DoFHandler<dim,spacedim> &coarse_grid,
- const unsigned int coarse_component,
- const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
- const std::vector<dealii::Vector<double> > ¶meter_dofs,
- const std::vector<types::global_dof_index> &weight_mapping,
- std::vector<std::map<types::global_dof_index,float> > &weights)
- {
- // simply distribute the range of cells to different threads
- typedef typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator active_cell_iterator;
- std::vector<std::pair<active_cell_iterator,active_cell_iterator> >
- cell_intervals = Threads::split_range<active_cell_iterator> (coarse_grid.begin_active(),
- coarse_grid.end(),
- multithread_info.n_default_threads);
-
- // TODO: use WorkStream here
-
- Threads::TaskGroup<> tasks;
- void (*fun_ptr) (const dealii::DoFHandler<dim,spacedim> &,
- const unsigned int ,
- const InterGridMap<dealii::DoFHandler<dim,spacedim> > &,
- const std::vector<dealii::Vector<double> > &,
- const std::vector<types::global_dof_index> &,
- std::vector<std::map<types::global_dof_index, float> > &,
- const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &,
- const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &)
- = &compute_intergrid_weights_3<dim>;
- for (unsigned int i=0; i<multithread_info.n_default_threads; ++i)
- tasks += Threads::new_task (fun_ptr,
- coarse_grid, coarse_component,
- coarse_to_fine_grid_map, parameter_dofs,
- weight_mapping, weights,
- cell_intervals[i].first,
- cell_intervals[i].second);
-
- // wait for the tasks to finish
- tasks.join_all ();
- }
-
-
-
- /**
- * This is a helper function that is used in the computation of
- * integrid constraints. See the function for a thorough description
- * of how it works.
- */
- template <int dim, int spacedim>
- unsigned int
- compute_intergrid_weights_1 (
- const dealii::DoFHandler<dim,spacedim> &coarse_grid,
- const unsigned int coarse_component,
- const dealii::DoFHandler<dim,spacedim> &fine_grid,
- const unsigned int fine_component,
- const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
- std::vector<std::map<types::global_dof_index, float> > &weights,
- std::vector<types::global_dof_index> &weight_mapping)
- {
- // aliases to the finite elements used by the dof handlers:
- const FiniteElement<dim,spacedim> &coarse_fe = coarse_grid.get_fe(),
- &fine_fe = fine_grid.get_fe();
-
- // global numbers of dofs
- const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs(),
- n_fine_dofs = fine_grid.n_dofs();
-
- // local numbers of dofs
- const unsigned int fine_dofs_per_cell = fine_fe.dofs_per_cell;
-
- // alias the number of dofs per cell belonging to the
- // coarse_component which is to be the restriction of the fine
- // grid:
- const unsigned int coarse_dofs_per_cell_component
- = coarse_fe.base_element(coarse_fe.component_to_base_index(coarse_component).first).dofs_per_cell;
-
-
- // Try to find out whether the grids stem from the same coarse
- // grid. This is a rather crude test, but better than nothing
- Assert (coarse_grid.get_tria().n_cells(0) == fine_grid.get_tria().n_cells(0),
- ExcGridsDontMatch());
-
- // check whether the map correlates the right objects
- Assert (&coarse_to_fine_grid_map.get_source_grid() == &coarse_grid,
- ExcGridsDontMatch ());
- Assert (&coarse_to_fine_grid_map.get_destination_grid() == &fine_grid,
- ExcGridsDontMatch ());
-
-
- // check whether component numbers are valid
- AssertIndexRange (coarse_component,coarse_fe.n_components());
- AssertIndexRange (fine_component, fine_fe.n_components());
-
- // check whether respective finite elements are equal
- Assert (coarse_fe.base_element (coarse_fe.component_to_base_index(coarse_component).first)
- ==
- fine_fe.base_element (fine_fe.component_to_base_index(fine_component).first),
- ExcFiniteElementsDontMatch());
-
-#ifdef DEBUG
- // if in debug mode, check whether the coarse grid is indeed
- // coarser everywhere than the fine grid
- for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
- cell=coarse_grid.begin_active();
- cell != coarse_grid.end(); ++cell)
- Assert (cell->level() <= coarse_to_fine_grid_map[cell]->level(),
- ExcGridNotCoarser());
-#endif
-
- /*
- * From here on: the term `parameter' refers to the selected
- * component on the coarse grid and its analogon on the fine grid.
- * The naming of variables containing this term is due to the fact
- * that `selected_component' is longer, but also due to the fact
- * that the code of this function was initially written for a
- * program where the component which we wanted to match between
- * grids was actually the `parameter' variable.
- *
- * Likewise, the terms `parameter grid' and `state grid' refer to
- * the coarse and fine grids, respectively.
- *
- * Changing the names of variables would in principle be a good
- * idea, but would not make things simpler and would be another
- * source of errors. If anyone feels like doing so: patches would
- * be welcome!
- */
-
-
-
- // set up vectors of cell-local data; each vector represents one
- // degree of freedom of the coarse-grid variable in the fine-grid
- // element
- std::vector<dealii::Vector<double> >
- parameter_dofs (coarse_dofs_per_cell_component,
- dealii::Vector<double>(fine_dofs_per_cell));
- // for each coarse dof: find its position within the fine element
- // and set this value to one in the respective vector (all other
- // values are zero by construction)
- for (unsigned int local_coarse_dof=0;
- local_coarse_dof<coarse_dofs_per_cell_component;
- ++local_coarse_dof)
- for (unsigned int fine_dof=0; fine_dof<fine_fe.dofs_per_cell; ++fine_dof)
- if (fine_fe.system_to_component_index(fine_dof)
- ==
- std::make_pair (fine_component, local_coarse_dof))
- {
- parameter_dofs[local_coarse_dof](fine_dof) = 1.;
- break;
- };
-
-
- // find out how many DoFs there are on the grids belonging to the
- // components we want to match
- unsigned int n_parameters_on_fine_grid=0;
- if (true)
- {
- // have a flag for each dof on the fine grid and set it to true
- // if this is an interesting dof. finally count how many true's
- // there
- std::vector<bool> dof_is_interesting (fine_grid.n_dofs(), false);
- std::vector<types::global_dof_index> local_dof_indices (fine_fe.dofs_per_cell);
-
- for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
- cell=fine_grid.begin_active();
- cell!=fine_grid.end(); ++cell)
- {
- cell->get_dof_indices (local_dof_indices);
- for (unsigned int i=0; i<fine_fe.dofs_per_cell; ++i)
- if (fine_fe.system_to_component_index(i).first == fine_component)
- dof_is_interesting[local_dof_indices[i]] = true;
- };
-
- n_parameters_on_fine_grid = std::count (dof_is_interesting.begin(),
- dof_is_interesting.end(),
- true);
- };
-
-
- // set up the weights mapping
- weights.clear ();
- weights.resize (n_coarse_dofs);
-
- weight_mapping.clear ();
- weight_mapping.resize (n_fine_dofs, numbers::invalid_dof_index);
-
- if (true)
- {
- std::vector<types::global_dof_index> local_dof_indices(fine_fe.dofs_per_cell);
- unsigned int next_free_index=0;
- for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
- cell=fine_grid.begin_active();
- cell != fine_grid.end(); ++cell)
- {
- cell->get_dof_indices (local_dof_indices);
- for (unsigned int i=0; i<fine_fe.dofs_per_cell; ++i)
- // if this DoF is a parameter dof and has not yet been
- // numbered, then do so
- if ((fine_fe.system_to_component_index(i).first == fine_component) &&
- (weight_mapping[local_dof_indices[i]] == numbers::invalid_dof_index))
- {
- weight_mapping[local_dof_indices[i]] = next_free_index;
- ++next_free_index;
- };
- };
-
- Assert (next_free_index == n_parameters_on_fine_grid,
- ExcInternalError());
- };
-
-
- // for each cell on the parameter grid: find out which degrees of
- // freedom on the fine grid correspond in which way to the degrees
- // of freedom on the parameter grid
- //
- // do this in a separate function to allow for multithreading
- // there. see this function also if you want to read more
- // information on the algorithm used.
- compute_intergrid_weights_2 (coarse_grid, coarse_component,
- coarse_to_fine_grid_map, parameter_dofs,
- weight_mapping, weights);
-
-
- // ok, now we have all weights for each dof on the fine grid. if in
- // debug mode lets see if everything went smooth, i.e. each dof has
- // sum of weights one
- //
- // in other words this means that if the sum of all shape functions
- // on the parameter grid is one (which is always the case), then
- // the representation on the state grid should be as well (division
- // of unity)
- //
- // if the parameter grid has more than one component, then the
- // respective dofs of the other components have sum of weights
- // zero, of course. we do not explicitly ask which component a dof
- // belongs to, but this at least tests some errors
-#ifdef DEBUG
- for (unsigned int col=0; col<n_parameters_on_fine_grid; ++col)
- {
- double sum=0;
- for (types::global_dof_index row=0; row<n_coarse_dofs; ++row)
- if (weights[row].find(col) != weights[row].end())
- sum += weights[row][col];
- Assert ((std::fabs(sum-1) < 1.e-12) ||
- ((coarse_fe.n_components()>1) && (sum==0)), ExcInternalError());
- };
-#endif
-
-
- return n_parameters_on_fine_grid;
- }
-
-
- }
- }
-
-
-
- template <int dim, int spacedim>
- void
- compute_intergrid_constraints (
- const DoFHandler<dim,spacedim> &coarse_grid,
- const unsigned int coarse_component,
- const DoFHandler<dim,spacedim> &fine_grid,
- const unsigned int fine_component,
- const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
- ConstraintMatrix &constraints)
- {
- // store the weights with which a dof on the parameter grid contributes
- // to a dof on the fine grid. see the long doc below for more info
- //
- // allocate as many rows as there are parameter dofs on the coarse grid
- // and as many columns as there are parameter dofs on the fine grid.
- //
- // weight_mapping is used to map the global (fine grid) parameter dof
- // indices to the columns
- //
- // in the original implementation, the weights array was actually of
- // FullMatrix<double> type. this wasted huge amounts of memory, but was
- // fast. nonetheless, since the memory consumption was quadratic in the
- // number of degrees of freedom, this was not very practical, so we now
- // use a vector of rows of the matrix, and in each row a vector of
- // pairs (colnum,value). this seems like the best tradeoff between
- // memory and speed, as it is now linear in memory and still fast
- // enough.
- //
- // to save some memory and since the weights are usually (negative)
- // powers of 2, we choose the value type of the matrix to be @p{float}
- // rather than @p{double}.
- std::vector<std::map<types::global_dof_index, float> > weights;
-
- // this is this mapping. there is one entry for each dof on the fine
- // grid; if it is a parameter dof, then its value is the column in
- // weights for that parameter dof, if it is any other dof, then its
- // value is -1, indicating an error
- std::vector<types::global_dof_index> weight_mapping;
-
- const unsigned int n_parameters_on_fine_grid
- = internal::compute_intergrid_weights_1 (coarse_grid, coarse_component,
- fine_grid, fine_component,
- coarse_to_fine_grid_map,
- weights, weight_mapping);
-
- // global numbers of dofs
- const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs(),
- n_fine_dofs = fine_grid.n_dofs();
-
-
- // get an array in which we store which dof on the coarse grid is a
- // parameter and which is not
- std::vector<bool> coarse_dof_is_parameter (coarse_grid.n_dofs());
- if (true)
- {
- std::vector<bool> mask (coarse_grid.get_fe().n_components(),
- false);
- mask[coarse_component] = true;
- extract_dofs (coarse_grid, ComponentMask(mask), coarse_dof_is_parameter);
- }
-
- // now we know that the weights in each row constitute a constraint.
- // enter this into the constraints object
- //
- // first task: for each parameter dof on the parameter grid, find a
- // representant on the fine, global grid. this is possible since we use
- // conforming finite element. we take this representant to be the first
- // element in this row with weight identical to one. the representant
- // will become an unconstrained degree of freedom, while all others
- // will be constrained to this dof (and possibly others)
- std::vector<types::global_dof_index> representants(n_coarse_dofs, numbers::invalid_dof_index);
- for (types::global_dof_index parameter_dof=0; parameter_dof<n_coarse_dofs;
- ++parameter_dof)
- if (coarse_dof_is_parameter[parameter_dof] == true)
- {
- // if this is the line of a parameter dof on the coarse grid,
- // then it should have at least one dependent node on the fine
- // grid
- Assert (weights[parameter_dof].size() > 0, ExcInternalError());
-
- // find the column where the representant is mentioned
- std::map<types::global_dof_index,float>::const_iterator i = weights[parameter_dof].begin();
- for (; i!=weights[parameter_dof].end(); ++i)
- if (i->second == 1)
- break;
- Assert (i!=weights[parameter_dof].end(), ExcInternalError());
- const types::global_dof_index column = i->first;
-
- // now we know in which column of weights the representant is,
- // but we don't know its global index. get it using the inverse
- // operation of the weight_mapping
- types::global_dof_index global_dof=0;
- for (; global_dof<weight_mapping.size(); ++global_dof)
- if (weight_mapping[global_dof] == static_cast<types::global_dof_index>(column))
- break;
- Assert (global_dof < weight_mapping.size(), ExcInternalError());
-
- // now enter the representants global index into our list
- representants[parameter_dof] = global_dof;
- }
- else
- {
- // consistency check: if this is no parameter dof on the coarse
- // grid, then the respective row must be empty!
- Assert (weights[parameter_dof].size() == 0, ExcInternalError());
- };
-
-
-
- // note for people that want to optimize this function: the largest
- // part of the computing time is spent in the following, rather
- // innocent block of code. basically, it must be the
- // ConstraintMatrix::add_entry call which takes the bulk of the time,
- // but it is not known to the author how to make it faster...
- std::vector<std::pair<types::global_dof_index,double> > constraint_line;
- for (types::global_dof_index global_dof=0; global_dof<n_fine_dofs; ++global_dof)
- if (weight_mapping[global_dof] != numbers::invalid_dof_index)
- // this global dof is a parameter dof, so it may carry a constraint
- // note that for each global dof, the sum of weights shall be one,
- // so we can find out whether this dof is constrained in the
- // following way: if the only weight in this row is a one, and the
- // representant for the parameter dof of the line in which this one
- // is is the present dof, then we consider this dof to be
- // unconstrained. otherwise, all other dofs are constrained
- {
- const types::global_dof_index col = weight_mapping[global_dof];
- Assert (col < n_parameters_on_fine_grid, ExcInternalError());
-
- types::global_dof_index first_used_row=0;
-
- {
- Assert (weights.size() > 0, ExcInternalError());
- std::map<types::global_dof_index,float>::const_iterator
- col_entry = weights[0].end();
- for (; first_used_row<n_coarse_dofs; ++first_used_row)
- {
- col_entry = weights[first_used_row].find(col);
- if (col_entry != weights[first_used_row].end())
- break;
- }
-
- Assert (col_entry != weights[first_used_row].end(), ExcInternalError());
-
- if ((col_entry->second == 1) &&
- (representants[first_used_row] == global_dof))
- // dof unconstrained or constrained to itself (in case this
- // cell is mapped to itself, rather than to children of
- // itself)
- continue;
- }
-
-
- // otherwise enter all constraints
- constraints.add_line (global_dof);
-
- constraint_line.clear ();
- for (types::global_dof_index row=first_used_row; row<n_coarse_dofs; ++row)
- {
- const std::map<types::global_dof_index,float>::const_iterator
- j = weights[row].find(col);
- if ((j != weights[row].end()) && (j->second != 0))
- constraint_line.push_back (std::pair<types::global_dof_index,double>(representants[row],
- j->second));
- };
-
- constraints.add_entries (global_dof, constraint_line);
- };
- }
-
-
-
- template <int dim, int spacedim>
- void
- compute_intergrid_transfer_representation (
- const DoFHandler<dim,spacedim> &coarse_grid,
- const unsigned int coarse_component,
- const DoFHandler<dim,spacedim> &fine_grid,
- const unsigned int fine_component,
- const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
- std::vector<std::map<types::global_dof_index, float> > &transfer_representation)
- {
- // store the weights with which a dof on the parameter grid contributes
- // to a dof on the fine grid. see the long doc below for more info
- //
- // allocate as many rows as there are parameter dofs on the coarse grid
- // and as many columns as there are parameter dofs on the fine grid.
- //
- // weight_mapping is used to map the global (fine grid) parameter dof
- // indices to the columns
- //
- // in the original implementation, the weights array was actually of
- // FullMatrix<double> type. this wasted huge amounts of memory, but was
- // fast. nonetheless, since the memory consumption was quadratic in the
- // number of degrees of freedom, this was not very practical, so we now
- // use a vector of rows of the matrix, and in each row a vector of
- // pairs (colnum,value). this seems like the best tradeoff between
- // memory and speed, as it is now linear in memory and still fast
- // enough.
- //
- // to save some memory and since the weights are usually (negative)
- // powers of 2, we choose the value type of the matrix to be @p{float}
- // rather than @p{double}.
- std::vector<std::map<types::global_dof_index, float> > weights;
-
- // this is this mapping. there is one entry for each dof on the fine
- // grid; if it is a parameter dof, then its value is the column in
- // weights for that parameter dof, if it is any other dof, then its
- // value is -1, indicating an error
- std::vector<types::global_dof_index> weight_mapping;
-
- internal::compute_intergrid_weights_1 (coarse_grid, coarse_component,
- fine_grid, fine_component,
- coarse_to_fine_grid_map,
- weights, weight_mapping);
-
- // now compute the requested representation
- const types::global_dof_index n_global_parm_dofs
- = std::count_if (weight_mapping.begin(), weight_mapping.end(),
- std::bind2nd (std::not_equal_to<types::global_dof_index> (), numbers::invalid_dof_index));
-
- // first construct the inverse mapping of weight_mapping
- std::vector<types::global_dof_index> inverse_weight_mapping (n_global_parm_dofs,
- DoFHandler<dim,spacedim>::invalid_dof_index);
- for (types::global_dof_index i=0; i<weight_mapping.size(); ++i)
- {
- const types::global_dof_index parameter_dof = weight_mapping[i];
- // if this global dof is a parameter
- if (parameter_dof != numbers::invalid_dof_index)
- {
- Assert (parameter_dof < n_global_parm_dofs, ExcInternalError());
- Assert ((inverse_weight_mapping[parameter_dof] == DoFHandler<dim,spacedim>::invalid_dof_index),
- ExcInternalError());
-
- inverse_weight_mapping[parameter_dof] = i;
- };
- };
-
- // next copy over weights array and replace respective numbers
- const types::global_dof_index n_rows = weight_mapping.size();
-
- transfer_representation.clear ();
- transfer_representation.resize (n_rows);
-
- const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs();
- for (types::global_dof_index i=0; i<n_coarse_dofs; ++i)
- {
- std::map<types::global_dof_index, float>::const_iterator j = weights[i].begin();
- for (; j!=weights[i].end(); ++j)
- {
- const types::global_dof_index p = inverse_weight_mapping[j->first];
- Assert (p<n_rows, ExcInternalError());
-
- transfer_representation[p][i] = j->second;
- };
- };
- }
-
-
-
template <class DH>
void
map_dof_to_boundary_indices (const DH &dof_handler,
- template <int dim, int spacedim, template <int,int> class DH>
- void
- make_zero_boundary_constraints (const DH<dim, spacedim> &dof,
- const types::boundary_id boundary_indicator,
- ConstraintMatrix &zero_boundary_constraints,
- const ComponentMask &component_mask)
- {
- Assert (component_mask.represents_n_components(dof.get_fe().n_components()),
- ExcMessage ("The number of components in the mask has to be either "
- "zero or equal to the number of components in the finite "
- "element."));
-
- const unsigned int n_components = DoFTools::n_components (dof);
-
- Assert (component_mask.n_selected_components(n_components) > 0,
- VectorTools::ExcNoComponentSelected());
-
- // a field to store the indices
- std::vector<types::global_dof_index> face_dofs;
- face_dofs.reserve (max_dofs_per_face(dof));
-
- typename DH<dim,spacedim>::active_cell_iterator
- cell = dof.begin_active(),
- endc = dof.end();
- for (; cell!=endc; ++cell)
- if (!cell->is_artificial())
- for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
- ++face_no)
- {
- const FiniteElement<dim,spacedim> &fe = cell->get_fe();
-
- const typename DH<dim,spacedim>::face_iterator face = cell->face(face_no);
-
- // if face is on the boundary and satisfies the correct
- // boundary id property
- if (face->at_boundary ()
- &&
- ((boundary_indicator == numbers::invalid_boundary_id)
- ||
- (face->boundary_indicator() == boundary_indicator)))
- {
- // get indices and physical location on this face
- face_dofs.resize (fe.dofs_per_face);
- face->get_dof_indices (face_dofs, cell->active_fe_index());
-
- // enter those dofs into the list that match the component
- // signature.
- for (unsigned int i=0; i<face_dofs.size(); ++i)
- {
- // Find out if a dof has a contribution in this
- // component, and if so, add it to the list
- const ComponentMask &nonzero_component_array
- = cell->get_fe().get_nonzero_components (i);
- bool nonzero = false;
- for (unsigned int c=0; c<n_components; ++c)
- if (nonzero_component_array[c] && component_mask[c])
- {
- nonzero = true;
- break;
- }
-
- if (nonzero)
- zero_boundary_constraints.add_line (face_dofs[i]);
- }
- }
- }
- }
-
-
-
- template <int dim, int spacedim, template <int,int> class DH>
- void
- make_zero_boundary_constraints (const DH<dim, spacedim> &dof,
- ConstraintMatrix &zero_boundary_constraints,
- const ComponentMask &component_mask)
- {
- make_zero_boundary_constraints(dof, numbers::invalid_boundary_id,
- zero_boundary_constraints, component_mask);
- }
-
-
template <class DH, class Sparsity>
void make_cell_patches(
Sparsity &block_list,
}
}
}
-}
+
+
+} // end of namespace DoFTools
// ---------------------------------------------------------------------
-
for (SP : SPARSITY_PATTERNS; deal_II_dimension : DIMENSIONS)
{
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
- (const DoFHandler<deal_II_dimension,deal_II_dimension> &dof,
- SP &sparsity,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
- (const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof,
- SP &sparsity,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<MGDoFHandler<deal_II_dimension,deal_II_dimension>, SP>
- (const MGDoFHandler<deal_II_dimension,deal_II_dimension> &dof,
- SP &sparsity,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
- (const DoFHandler<deal_II_dimension,deal_II_dimension>&,
- const Table<2,Coupling>&,
- SP &,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
- (const hp::DoFHandler<deal_II_dimension,deal_II_dimension>&,
- const Table<2,Coupling>&,
- SP &,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<MGDoFHandler<deal_II_dimension,deal_II_dimension>, SP>
- (const MGDoFHandler<deal_II_dimension,deal_II_dimension>&,
- const Table<2,Coupling>&,
- SP &,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
- (const DoFHandler<deal_II_dimension,deal_II_dimension> &dof_row,
- const DoFHandler<deal_II_dimension,deal_II_dimension> &dof_col,
- SP &sparsity);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
- (const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof_row,
- const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof_col,
- SP &sparsity);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
- (const DoFHandler<deal_II_dimension>& dof,
- const std::vector<types::global_dof_index> &,
- SP &);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
- (const hp::DoFHandler<deal_II_dimension>& dof,
- const std::vector<types::global_dof_index> &,
- SP &);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
- (const DoFHandler<deal_II_dimension>& dof,
- const FunctionMap<deal_II_dimension>::type &boundary_indicators,
- const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- SP &sparsity);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
- (const hp::DoFHandler<deal_II_dimension>& dof,
- const FunctionMap<deal_II_dimension>::type &boundary_indicators,
- const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- SP &sparsity);
-
-#if deal_II_dimension < 3
- template void
- DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
- (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
- const FunctionMap<deal_II_dimension+1>::type &boundary_indicators,
- const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- SP &sparsity);
- #endif
-
- template void
- DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
- (const DoFHandler<deal_II_dimension> &dof,
- SP &sparsity);
-
- template void
- DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
- (const hp::DoFHandler<deal_II_dimension> &dof,
- SP &sparsity);
-
- template void
- DoFTools::make_cell_patches<DoFHandler<deal_II_dimension>,SP>
- (SP&, const DoFHandler<deal_II_dimension>&, const unsigned int, const std::vector<bool>&, types::global_dof_index);
-
- template void
- DoFTools::make_cell_patches<MGDoFHandler<deal_II_dimension>,SP>
- (SP&, const MGDoFHandler<deal_II_dimension>&, const unsigned int, const std::vector<bool>&, types::global_dof_index);
-
-#if deal_II_dimension > 1
-
- template void
- DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
- (const DoFHandler<deal_II_dimension> &dof,
- SP &,
- const Table<2,Coupling>&,
- const Table<2,Coupling>&);
-
- template void
- DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
- (const DoFHandler<deal_II_dimension> &dof,
- SP &sparsity,
- const ConstraintMatrix &constraints,
- const bool, const unsigned int);
-
- template void
- DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
- (const hp::DoFHandler<deal_II_dimension> &dof,
- SP &sparsity,
- const ConstraintMatrix &constraints,
- const bool, const unsigned int);
-
- template void
- DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
- (const hp::DoFHandler<deal_II_dimension> &dof,
- SP &,
- const Table<2,Coupling>&,
- const Table<2,Coupling>&);
-#endif
-
-#if deal_II_dimension < 3
-
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
- (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof,
- SP &sparsity,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
- (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof,
- SP &sparsity,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
- (const DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
- const Table<2,Coupling>&,
- SP &,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
- (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
- const Table<2,Coupling>&,
- SP &,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
- (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_row,
- const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_col,
- SP &sparsity);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
- (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_row,
- const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_col,
- SP &sparsity);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
- (const DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
- const std::vector<types::global_dof_index> &,
- SP &);
-
- //template void
- //DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
- //(const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
- // const std::vector<types::global_dof_index> &,
- // SP &);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
- (const DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
- const FunctionMap<deal_II_dimension+1>::type &boundary_indicators,
- const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- SP &sparsity);
-
- //template void
- //DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
- //(const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
- // const FunctionMap<deal_II_dimension+1>::type &boundary_indicators,
- // const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- // SP &sparsity);
-
-#endif
-
-
-#if deal_II_dimension == 3
-
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
- (const DoFHandler<1,3> &dof,
- SP &sparsity,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
- (const hp::DoFHandler<1,3> &dof,
- SP &sparsity,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
- (const DoFHandler<1,3>&,
- const Table<2,Coupling>&,
- SP &,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
- (const hp::DoFHandler<1,3>&,
- const Table<2,Coupling>&,
- SP &,
- const ConstraintMatrix &,
- const bool,
- const unsigned int);
-
- template void
- DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
- (const DoFHandler<1,3> &dof_row,
- const DoFHandler<1,3> &dof_col,
- SP &sparsity);
-
- template void
- DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
- (const hp::DoFHandler<1,3> &dof_row,
- const hp::DoFHandler<1,3> &dof_col,
- SP &sparsity);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<DoFHandler<1,3>,SP>
- (const DoFHandler<1,3>& dof,
- const std::vector<types::global_dof_index> &,
- SP &);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<1,3>,SP>
- (const hp::DoFHandler<1,3>& dof,
- const std::vector<types::global_dof_index> &,
- SP &);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<DoFHandler<1,3>,SP>
- (const DoFHandler<1,3>& dof,
- const FunctionMap<3>::type &boundary_indicators,
- const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- SP &sparsity);
-
- template void
- DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<1,3>,SP>
- (const hp::DoFHandler<1,3>& dof,
- const FunctionMap<3>::type &boundary_indicators,
- const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
- SP &sparsity);
-
-#endif
-
- }
-
+ template void
+ DoFTools::make_cell_patches<DoFHandler<deal_II_dimension>,SP>
+ (SP&, const DoFHandler<deal_II_dimension>&, const unsigned int, const std::vector<bool>&, types::global_dof_index);
-
-
-for (DH : DOFHANDLERS; deal_II_dimension : DIMENSIONS)
-{
- template
- void
- DoFTools::make_hanging_node_constraints (const DH &dof_handler,
- ConstraintMatrix &constraints);
-}
-
-
-
-for (DH : DOFHANDLERS; deal_II_dimension : DIMENSIONS)
-{
-
-#if deal_II_dimension != 1
- template
- void
- DoFTools::make_periodicity_constraints (const DH::face_iterator &,
- const DH::face_iterator &,
- dealii::ConstraintMatrix &,
- const ComponentMask &,
- bool, bool, bool);
-
- template
- void
- DoFTools::make_periodicity_constraints(const DH &,
- const types::boundary_id,
- const types::boundary_id,
- const int,
- dealii::ConstraintMatrix &,
- const ComponentMask &);
-
- template
- void
- DoFTools::make_periodicity_constraints(const DH &,
- const types::boundary_id,
- const types::boundary_id,
- const int,
- dealii::Tensor<1,DH::space_dimension> &,
- dealii::ConstraintMatrix &,
- const ComponentMask &);
-
- template
- void
- DoFTools::make_periodicity_constraints(const DH &,
- const types::boundary_id,
- const int,
- dealii::ConstraintMatrix &,
- const ComponentMask &);
-
- template
- void
- DoFTools::make_periodicity_constraints(const DH &,
- const types::boundary_id,
- const int,
- dealii::Tensor<1,DH::space_dimension> &,
- dealii::ConstraintMatrix &,
- const ComponentMask &);
-#endif
+ template void
+ DoFTools::make_cell_patches<MGDoFHandler<deal_II_dimension>,SP>
+ (SP&, const MGDoFHandler<deal_II_dimension>&, const unsigned int, const std::vector<bool>&, types::global_dof_index);
}
-for (deal_II_dimension : DIMENSIONS)
-{
-#if deal_II_dimension != 1
- template
- void
- DoFTools::make_hanging_node_constraints (const MGDoFHandler<deal_II_dimension> &dof_handler,
- ConstraintMatrix &constraints);
-
-#endif
- }
for (deal_II_dimension : DIMENSIONS)
{
- template
- Table<2,DoFTools::Coupling>
- DoFTools::dof_couplings_from_component_couplings
- (const FiniteElement<deal_II_dimension> &fe,
- const Table<2,DoFTools::Coupling> &component_couplings);
-
template
void DoFTools::make_vertex_patches (SparsityPattern&, const DoFHandler<deal_II_dimension>&,
unsigned int, bool, bool, bool, bool);
void DoFTools::make_child_patches(SparsityPattern&, const MGDoFHandler<deal_II_dimension>&,
unsigned int, bool, bool);
-#if deal_II_dimension < 3
-template
-void
-DoFTools::
-make_hanging_node_constraints (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_handler,
- ConstraintMatrix &constraints);
-#endif
-
-#if deal_II_dimension == 3
-template
-void
-DoFTools::
-make_hanging_node_constraints (const DoFHandler<1,3> &dof_handler,
- ConstraintMatrix &constraints);
-#endif
-
// TODO: can cleanup a bit more to fit into the scheme used above
const DoFHandler<deal_II_dimension>&,
std::vector<types::global_dof_index>&, std::vector<unsigned int>);
-template
-void
-DoFTools::compute_intergrid_constraints<deal_II_dimension> (
- const DoFHandler<deal_II_dimension> &, const unsigned int,
- const DoFHandler<deal_II_dimension> &, const unsigned int,
- const InterGridMap<DoFHandler<deal_II_dimension> > &,
- ConstraintMatrix&);
-
-template
-void
-DoFTools::compute_intergrid_transfer_representation<deal_II_dimension>
-(const DoFHandler<deal_II_dimension> &, const unsigned int,
- const DoFHandler<deal_II_dimension> &, const unsigned int,
- const InterGridMap<DoFHandler<deal_II_dimension> > &,
- std::vector<std::map<types::global_dof_index, float> > &);
-
-
template
void
DoFTools::map_dof_to_boundary_indices<DoFHandler<deal_II_dimension> >
const hp::DoFHandler<deal_II_dimension>&, const Table<2, Coupling>&,
std::vector<Table<2,Coupling> >&);
-template
-void
-DoFTools::make_zero_boundary_constraints
-(const DoFHandler<deal_II_dimension> &,
- ConstraintMatrix &,
- const ComponentMask &);
-
-template
-void
-DoFTools::make_zero_boundary_constraints
-(const DoFHandler<deal_II_dimension> &,
- const types::boundary_id ,
- ConstraintMatrix &,
- const ComponentMask &);
-
-template
-void
-DoFTools::make_zero_boundary_constraints
-(const hp::DoFHandler<deal_II_dimension> &,
- ConstraintMatrix &,
- const ComponentMask &);
-
-template
-void
-DoFTools::make_zero_boundary_constraints
-(const hp::DoFHandler<deal_II_dimension> &,
- const types::boundary_id ,
- ConstraintMatrix &,
- const ComponentMask &);
-
#if deal_II_dimension < 3
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/multithread_info.h>
+#include <deal.II/base/thread_management.h>
+#include <deal.II/base/table.h>
+#include <deal.II/base/template_constraints.h>
+#include <deal.II/base/utilities.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/intergrid_map.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/fe/fe.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/fe_tools.h>
+#include <deal.II/hp/fe_collection.h>
+#include <deal.II/hp/fe_values.h>
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/multigrid/mg_dof_handler.h>
+
+#include <algorithm>
+#include <numeric>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+namespace DoFTools
+{
+ namespace internal
+ {
+ namespace
+ {
+ inline bool
+ check_master_dof_list (const FullMatrix<double> &face_interpolation_matrix,
+ const std::vector<types::global_dof_index> &master_dof_list)
+ {
+ const unsigned int N = master_dof_list.size();
+
+ FullMatrix<double> tmp (N,N);
+ for (unsigned int i=0; i<N; ++i)
+ for (unsigned int j=0; j<N; ++j)
+ tmp(i,j) = face_interpolation_matrix (master_dof_list[i], j);
+
+ // then use the algorithm from FullMatrix::gauss_jordan on this
+ // matrix to find out whether it is singular. the algorithm there
+ // does piviting and at the end swaps rows back into their proper
+ // order -- we omit this step here, since we don't care about the
+ // inverse matrix, all we care about is whether the matrix is
+ // regular or singular
+
+ // first get an estimate of the size of the elements of this
+ // matrix, for later checks whether the pivot element is large
+ // enough, or whether we have to fear that the matrix is not
+ // regular
+ double diagonal_sum = 0;
+ for (unsigned int i=0; i<N; ++i)
+ diagonal_sum += std::fabs(tmp(i,i));
+ const double typical_diagonal_element = diagonal_sum/N;
+
+ // initialize the array that holds the permutations that we find
+ // during pivot search
+ std::vector<unsigned int> p(N);
+ for (unsigned int i=0; i<N; ++i)
+ p[i] = i;
+
+ for (unsigned int j=0; j<N; ++j)
+ {
+ // pivot search: search that part of the line on and right of
+ // the diagonal for the largest element
+ double max = std::fabs(tmp(j,j));
+ unsigned int r = j;
+ for (unsigned int i=j+1; i<N; ++i)
+ {
+ if (std::fabs(tmp(i,j)) > max)
+ {
+ max = std::fabs(tmp(i,j));
+ r = i;
+ }
+ }
+ // check whether the pivot is too small. if that is the case,
+ // then the matrix is singular and we shouldn't use this set of
+ // master dofs
+ if (max < 1.e-12*typical_diagonal_element)
+ return false;
+
+ // row interchange
+ if (r>j)
+ {
+ for (unsigned int k=0; k<N; ++k)
+ std::swap (tmp(j,k), tmp(r,k));
+
+ std::swap (p[j], p[r]);
+ }
+
+ // transformation
+ const double hr = 1./tmp(j,j);
+ tmp(j,j) = hr;
+ for (unsigned int k=0; k<N; ++k)
+ {
+ if (k==j) continue;
+ for (unsigned int i=0; i<N; ++i)
+ {
+ if (i==j) continue;
+ tmp(i,k) -= tmp(i,j)*tmp(j,k)*hr;
+ }
+ }
+ for (unsigned int i=0; i<N; ++i)
+ {
+ tmp(i,j) *= hr;
+ tmp(j,i) *= -hr;
+ }
+ tmp(j,j) = hr;
+ }
+
+ // everything went fine, so we can accept this set of master dofs
+ // (at least as far as they have already been collected)
+ return true;
+ }
+
+
+
+ /**
+ * When restricting, on a face, the degrees of freedom of fe1 to the
+ * space described by fe2 (for example for the complex case described
+ * in the @ref hp_paper "hp paper"), we have to select
+ * fe2.dofs_per_face out of the fe1.dofs_per_face face DoFs as the
+ * master DoFs, and the rest become slave dofs. This function selects
+ * which ones will be masters, and which ones will be slaves.
+ *
+ * The function assumes that master_dofs already has size
+ * fe1.dofs_per_face. After the function, exactly fe2.dofs_per_face
+ * entries will be true.
+ *
+ * The function is a bit complicated since it has to figure out a set
+ * a DoFs so that the corresponding rows in the face interpolation
+ * matrix are all linearly independent. we have a good heuristic (see
+ * the function body) for selecting these rows, but there are cases
+ * where this fails and we have to pick them differently. what we do
+ * is to run the heuristic and then go back to determine whether we
+ * have a set of rows with full row rank. if this isn't the case, go
+ * back and select dofs differently
+ */
+ template <int dim, int spacedim>
+ void
+ select_master_dofs_for_face_restriction (const FiniteElement<dim,spacedim> &fe1,
+ const FiniteElement<dim,spacedim> &fe2,
+ const FullMatrix<double> &face_interpolation_matrix,
+ std::vector<bool> &master_dof_mask)
+ {
+ Assert (fe1.dofs_per_face >= fe2.dofs_per_face,
+ ExcInternalError());
+ AssertDimension (master_dof_mask.size(), fe1.dofs_per_face);
+
+ Assert (fe2.dofs_per_vertex <= fe1.dofs_per_vertex,
+ ExcInternalError());
+ Assert (fe2.dofs_per_line <= fe1.dofs_per_line,
+ ExcInternalError());
+ Assert ((dim < 3)
+ ||
+ (fe2.dofs_per_quad <= fe1.dofs_per_quad),
+ ExcInternalError());
+
+ // the idea here is to designate as many DoFs in fe1 per object
+ // (vertex, line, quad) as master as there are such dofs in fe2
+ // (indices are int, because we want to avoid the 'unsigned int < 0
+ // is always false warning for the cases at the bottom in 1d and
+ // 2d)
+ //
+ // as mentioned in the paper, it is not always easy to find a set
+ // of master dofs that produces an invertible matrix. to this end,
+ // we check in each step whether the matrix is still invertible and
+ // simply discard this dof if the matrix is not invertible anymore.
+ //
+ // the cases where we did have trouble in the past were with adding
+ // more quad dofs when Q3 and Q4 elements meet at a refined face in
+ // 3d (see the hp/crash_12 test that tests that we can do exactly
+ // this, and failed before we had code to compensate for this
+ // case). the other case are system elements: if we have say a Q1Q2
+ // vs a Q2Q3 element, then we can't just take all master dofs on a
+ // line from a single base element, since the shape functions of
+ // that base element are independent of that of the other one. this
+ // latter case shows up when running hp/hp_constraints_q_system_06
+
+ std::vector<types::global_dof_index> master_dof_list;
+ unsigned int index = 0;
+ for (int v=0;
+ v<static_cast<signed int>(GeometryInfo<dim>::vertices_per_face);
+ ++v)
+ {
+ unsigned int dofs_added = 0;
+ unsigned int i = 0;
+ while (dofs_added < fe2.dofs_per_vertex)
+ {
+ // make sure that we were able to find a set of master dofs
+ // and that the code down below didn't just reject all our
+ // efforts
+ Assert (i < fe1.dofs_per_vertex,
+ ExcInternalError());
+
+ // tentatively push this vertex dof
+ master_dof_list.push_back (index+i);
+
+ // then see what happens. if it succeeds, fine
+ if (check_master_dof_list (face_interpolation_matrix,
+ master_dof_list)
+ == true)
+ ++dofs_added;
+ else
+ // well, it didn't. simply pop that dof from the list
+ // again and try with the next dof
+ master_dof_list.pop_back ();
+
+ // forward counter by one
+ ++i;
+ }
+ index += fe1.dofs_per_vertex;
+ }
+
+ for (int l=0;
+ l<static_cast<signed int>(GeometryInfo<dim>::lines_per_face);
+ ++l)
+ {
+ // same algorithm as above
+ unsigned int dofs_added = 0;
+ unsigned int i = 0;
+ while (dofs_added < fe2.dofs_per_line)
+ {
+ Assert (i < fe1.dofs_per_line,
+ ExcInternalError());
+
+ master_dof_list.push_back (index+i);
+ if (check_master_dof_list (face_interpolation_matrix,
+ master_dof_list)
+ == true)
+ ++dofs_added;
+ else
+ master_dof_list.pop_back ();
+
+ ++i;
+ }
+ index += fe1.dofs_per_line;
+ }
+
+ for (int q=0;
+ q<static_cast<signed int>(GeometryInfo<dim>::quads_per_face);
+ ++q)
+ {
+ // same algorithm as above
+ unsigned int dofs_added = 0;
+ unsigned int i = 0;
+ while (dofs_added < fe2.dofs_per_quad)
+ {
+ Assert (i < fe1.dofs_per_quad,
+ ExcInternalError());
+
+ master_dof_list.push_back (index+i);
+ if (check_master_dof_list (face_interpolation_matrix,
+ master_dof_list)
+ == true)
+ ++dofs_added;
+ else
+ master_dof_list.pop_back ();
+
+ ++i;
+ }
+ index += fe1.dofs_per_quad;
+ }
+
+ AssertDimension (index, fe1.dofs_per_face);
+ AssertDimension (master_dof_list.size(), fe2.dofs_per_face);
+
+ // finally copy the list into the mask
+ std::fill (master_dof_mask.begin(), master_dof_mask.end(), false);
+ for (std::vector<types::global_dof_index>::const_iterator i=master_dof_list.begin();
+ i!=master_dof_list.end(); ++i)
+ master_dof_mask[*i] = true;
+ }
+
+
+
+ /**
+ * Make sure that the mask exists that determines which dofs will be
+ * the masters on refined faces where an fe1 and a fe2 meet.
+ */
+ template <int dim, int spacedim>
+ void
+ ensure_existence_of_master_dof_mask (const FiniteElement<dim,spacedim> &fe1,
+ const FiniteElement<dim,spacedim> &fe2,
+ const FullMatrix<double> &face_interpolation_matrix,
+ std_cxx1x::shared_ptr<std::vector<bool> > &master_dof_mask)
+ {
+ if (master_dof_mask == std_cxx1x::shared_ptr<std::vector<bool> >())
+ {
+ master_dof_mask = std_cxx1x::shared_ptr<std::vector<bool> >
+ (new std::vector<bool> (fe1.dofs_per_face));
+ select_master_dofs_for_face_restriction (fe1,
+ fe2,
+ face_interpolation_matrix,
+ *master_dof_mask);
+ }
+ }
+
+
+
+ /**
+ * Make sure that the given @p face_interpolation_matrix pointer
+ * points to a valid matrix. If the pointer is zero beforehand,
+ * create an entry with the correct data. If it is nonzero, don't
+ * touch it.
+ */
+ template <int dim, int spacedim>
+ void
+ ensure_existence_of_face_matrix (const FiniteElement<dim,spacedim> &fe1,
+ const FiniteElement<dim,spacedim> &fe2,
+ std_cxx1x::shared_ptr<FullMatrix<double> > &matrix)
+ {
+ if (matrix == std_cxx1x::shared_ptr<FullMatrix<double> >())
+ {
+ matrix = std_cxx1x::shared_ptr<FullMatrix<double> >
+ (new FullMatrix<double> (fe2.dofs_per_face,
+ fe1.dofs_per_face));
+ fe1.get_face_interpolation_matrix (fe2,
+ *matrix);
+ }
+ }
+
+
+
+ /**
+ * Same, but for subface interpolation matrices.
+ */
+ template <int dim, int spacedim>
+ void
+ ensure_existence_of_subface_matrix (const FiniteElement<dim,spacedim> &fe1,
+ const FiniteElement<dim,spacedim> &fe2,
+ const unsigned int subface,
+ std_cxx1x::shared_ptr<FullMatrix<double> > &matrix)
+ {
+ if (matrix == std_cxx1x::shared_ptr<FullMatrix<double> >())
+ {
+ matrix = std_cxx1x::shared_ptr<FullMatrix<double> >
+ (new FullMatrix<double> (fe2.dofs_per_face,
+ fe1.dofs_per_face));
+ fe1.get_subface_interpolation_matrix (fe2,
+ subface,
+ *matrix);
+ }
+ }
+
+
+
+ /**
+ * Given the face interpolation matrix between two elements, split it
+ * into its master and slave parts and invert the master part as
+ * explained in the @ref hp_paper "hp paper".
+ */
+ void
+ ensure_existence_of_split_face_matrix (const FullMatrix<double> &face_interpolation_matrix,
+ const std::vector<bool> &master_dof_mask,
+ std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > > &split_matrix)
+ {
+ AssertDimension (master_dof_mask.size(), face_interpolation_matrix.m());
+ Assert (std::count (master_dof_mask.begin(), master_dof_mask.end(), true) ==
+ static_cast<signed int>(face_interpolation_matrix.n()),
+ ExcInternalError());
+
+ if (split_matrix ==
+ std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > >())
+ {
+ split_matrix
+ = std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > >
+ (new std::pair<FullMatrix<double>,FullMatrix<double> >());
+
+ const unsigned int n_master_dofs = face_interpolation_matrix.n();
+ const unsigned int n_dofs = face_interpolation_matrix.m();
+
+ Assert (n_master_dofs <= n_dofs, ExcInternalError());
+
+ // copy and invert the master
+ // component, copy the slave
+ // component
+ split_matrix->first.reinit (n_master_dofs, n_master_dofs);
+ split_matrix->second.reinit (n_dofs-n_master_dofs, n_master_dofs);
+
+ unsigned int nth_master_dof = 0,
+ nth_slave_dof = 0;
+
+ for (unsigned int i=0; i<n_dofs; ++i)
+ if (master_dof_mask[i] == true)
+ {
+ for (unsigned int j=0; j<n_master_dofs; ++j)
+ split_matrix->first(nth_master_dof,j)
+ = face_interpolation_matrix(i,j);
+ ++nth_master_dof;
+ }
+ else
+ {
+ for (unsigned int j=0; j<n_master_dofs; ++j)
+ split_matrix->second(nth_slave_dof,j)
+ = face_interpolation_matrix(i,j);
+ ++nth_slave_dof;
+ }
+
+ AssertDimension (nth_master_dof, n_master_dofs);
+ AssertDimension (nth_slave_dof, n_dofs-n_master_dofs);
+
+ //TODO[WB]: We should make sure very small entries are removed after inversion
+ split_matrix->first.gauss_jordan ();
+ }
+ }
+
+
+ // a template that can determine statically whether a given
+ // DoFHandler class supports different finite element elements
+ template <typename>
+ struct DoFHandlerSupportsDifferentFEs
+ {
+ static const bool value = true;
+ };
+
+
+ template <int dim, int spacedim>
+ struct DoFHandlerSupportsDifferentFEs< dealii::DoFHandler<dim,spacedim> >
+ {
+ static const bool value = false;
+ };
+
+
+ /**
+ * A function that returns how many different finite elements a dof
+ * handler uses. This is one for non-hp DoFHandlers and
+ * dof_handler.get_fe().size() for the hp-versions.
+ */
+ template <int dim, int spacedim>
+ unsigned int
+ n_finite_elements (const dealii::hp::DoFHandler<dim,spacedim> &dof_handler)
+ {
+ return dof_handler.get_fe().size();
+ }
+
+
+ template <class DH>
+ unsigned int
+ n_finite_elements (const DH &)
+ {
+ return 1;
+ }
+
+
+ /**
+ * For a given face belonging to an active cell that borders to a
+ * more refined cell, return the fe_index of the most dominating
+ * finite element used on any of the face's subfaces.
+ */
+ template <typename face_iterator>
+ unsigned int
+ get_most_dominating_subface_fe_index (const face_iterator &face)
+ {
+ const unsigned int dim
+ = face_iterator::AccessorType::dimension;
+ const unsigned int spacedim
+ = face_iterator::AccessorType::space_dimension;
+
+ unsigned int dominating_subface_no = 0;
+ for (; dominating_subface_no<face->n_children();
+ ++dominating_subface_no)
+ {
+ // each of the subfaces can have only a single fe_index
+ // associated with them, since there is no cell on the other
+ // side
+ Assert (face->child(dominating_subface_no)
+ ->n_active_fe_indices()
+ == 1,
+ ExcInternalError());
+
+ const FiniteElement<dim,spacedim> &
+ this_subface_fe = (face->child(dominating_subface_no)
+ ->get_fe (face->child(dominating_subface_no)
+ ->nth_active_fe_index(0)));
+
+ FiniteElementDomination::Domination
+ domination = FiniteElementDomination::either_element_can_dominate;
+ for (unsigned int sf=0; sf<face->n_children(); ++sf)
+ if (sf != dominating_subface_no)
+ {
+ const FiniteElement<dim,spacedim> &
+ that_subface_fe = (face->child(sf)
+ ->get_fe (face->child(sf)
+ ->nth_active_fe_index(0)));
+
+ domination = domination &
+ this_subface_fe.compare_for_face_domination(that_subface_fe);
+ }
+
+ // see if the element on this subface is able to dominate the
+ // ones on all other subfaces, and if so take it
+ if ((domination == FiniteElementDomination::this_element_dominates)
+ ||
+ (domination == FiniteElementDomination::either_element_can_dominate))
+ break;
+ }
+
+ // check that we have found one such subface
+ Assert (dominating_subface_no < face->n_children(),
+ ExcNotImplemented());
+
+ // return the finite element index used on it. note that only a
+ // single fe can be active on such subfaces
+ return face->child (dominating_subface_no)->nth_active_fe_index(0);
+ }
+
+
+
+ /**
+ * Copy constraints into a constraint matrix object.
+ *
+ * This function removes zero constraints and those, which constrain
+ * a DoF which was already eliminated in one of the previous steps of
+ * the hp hanging node procedure.
+ *
+ * It also suppresses very small entries in the constraint matrix to
+ * avoid making the sparsity pattern fuller than necessary.
+ */
+ void
+ filter_constraints (const std::vector<types::global_dof_index> &master_dofs,
+ const std::vector<types::global_dof_index> &slave_dofs,
+ const FullMatrix<double> &face_constraints,
+ ConstraintMatrix &constraints)
+ {
+ Assert (face_constraints.n () == master_dofs.size (),
+ ExcDimensionMismatch(master_dofs.size (),
+ face_constraints.n()));
+ Assert (face_constraints.m () == slave_dofs.size (),
+ ExcDimensionMismatch(slave_dofs.size (),
+ face_constraints.m()));
+
+ const unsigned int n_master_dofs = master_dofs.size ();
+ const unsigned int n_slave_dofs = slave_dofs.size ();
+
+ // check for a couple conditions that happened in parallel
+ // distributed mode
+ for (unsigned int row=0; row!=n_slave_dofs; ++row)
+ Assert (slave_dofs[row] != numbers::invalid_dof_index,
+ ExcInternalError());
+ for (unsigned int col=0; col!=n_master_dofs; ++col)
+ Assert (master_dofs[col] != numbers::invalid_dof_index,
+ ExcInternalError());
+
+
+ for (unsigned int row=0; row!=n_slave_dofs; ++row)
+ if (constraints.is_constrained (slave_dofs[row]) == false)
+ {
+ bool constraint_already_satisfied = false;
+
+ // Check if we have an identity constraint, which is already
+ // satisfied by unification of the corresponding global dof
+ // indices
+ for (unsigned int i=0; i<n_master_dofs; ++i)
+ if (face_constraints (row,i) == 1.0)
+ if (master_dofs[i] == slave_dofs[row])
+ {
+ constraint_already_satisfied = true;
+ break;
+ }
+
+ if (constraint_already_satisfied == false)
+ {
+ // add up the absolute values of all constraints in this
+ // line to get a measure of their absolute size
+ double abs_sum = 0;
+ for (unsigned int i=0; i<n_master_dofs; ++i)
+ abs_sum += std::abs (face_constraints(row,i));
+
+ // then enter those constraints that are larger than
+ // 1e-14*abs_sum. everything else probably originated
+ // from inexact inversion of matrices and similar
+ // effects. having those constraints in here will only
+ // lead to problems because it makes sparsity patterns
+ // fuller than necessary without producing any
+ // significant effect
+ constraints.add_line (slave_dofs[row]);
+ for (unsigned int i=0; i<n_master_dofs; ++i)
+ if ((face_constraints(row,i) != 0)
+ &&
+ (std::fabs(face_constraints(row,i)) >= 1e-14*abs_sum))
+ constraints.add_entry (slave_dofs[row],
+ master_dofs[i],
+ face_constraints (row,i));
+ constraints.set_inhomogeneity (slave_dofs[row], 0.);
+ }
+ }
+ }
+
+ }
+
+
+
+ void
+ make_hp_hanging_node_constraints (const dealii::DoFHandler<1> &,
+ ConstraintMatrix &)
+ {
+ // nothing to do for regular dof handlers in 1d
+ }
+
+
+
+ void
+ make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1> &,
+ ConstraintMatrix &,
+ dealii::internal::int2type<1>)
+ {
+ // nothing to do for regular dof handlers in 1d
+ }
+
+
+ void
+ make_hp_hanging_node_constraints (const dealii::MGDoFHandler<1> &,
+ ConstraintMatrix &)
+ {
+ // nothing to do for regular dof handlers in 1d
+ }
+
+
+
+ void
+ make_oldstyle_hanging_node_constraints (const dealii::MGDoFHandler<1> &,
+ ConstraintMatrix &,
+ dealii::internal::int2type<1>)
+ {
+ // nothing to do for regular dof handlers in 1d
+ }
+
+
+ void
+ make_hp_hanging_node_constraints (const dealii::hp::DoFHandler<1> &/*dof_handler*/,
+ ConstraintMatrix &/*constraints*/)
+ {
+ // we may have to compute constraints for vertices. gotta think about
+ // that a bit more
+
+ //TODO[WB]: think about what to do here...
+ }
+
+
+
+ void
+ make_oldstyle_hanging_node_constraints (const dealii::hp::DoFHandler<1> &/*dof_handler*/,
+ ConstraintMatrix &/*constraints*/,
+ dealii::internal::int2type<1>)
+ {
+ // we may have to compute constraints for vertices. gotta think about
+ // that a bit more
+
+ //TODO[WB]: think about what to do here...
+ }
+
+
+ void
+ make_hp_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
+ ConstraintMatrix &)
+ {
+ // nothing to do for regular dof handlers in 1d
+ }
+
+
+
+ void
+ make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
+ ConstraintMatrix &,
+ dealii::internal::int2type<1>)
+ {
+ // nothing to do for regular dof handlers in 1d
+ }
+
+
+ void
+ make_hp_hanging_node_constraints (const dealii::DoFHandler<1,3> &,
+ ConstraintMatrix &)
+ {
+ // nothing to do for regular dof handlers in 1d
+ }
+
+ void
+ make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,3> &,
+ ConstraintMatrix &,
+ dealii::internal::int2type<1>)
+ {
+ // nothing to do for regular dof handlers in 1d
+ }
+
+
+// currently not used but may be in the future:
+
+// void
+// make_hp_hanging_node_constraints (const dealii::MDoFHandler<1,2> &,
+// ConstraintMatrix &)
+// {
+// // nothing to do for regular
+// // dof handlers in 1d
+// }
+
+
+
+// void
+// make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
+// ConstraintMatrix &,
+// dealii::internal::int2type<1>)
+// {
+// // nothing to do for regular
+// // dof handlers in 1d
+// }
+
+
+// void
+// make_oldstyle_hanging_node_constraints (const dealii::hp::DoFHandler<1,2> &/*dof_handler*/,
+// ConstraintMatrix &/*constraints*/,
+// dealii::internal::int2type<1>)
+// {
+// // we may have to compute
+// // constraints for
+// // vertices. gotta think about
+// // that a bit more
+//
+// //TODO[WB]: think about what to do here...
+// }
+//#endif
+
+
+
+ template <class DH>
+ void
+ make_oldstyle_hanging_node_constraints (const DH &dof_handler,
+ ConstraintMatrix &constraints,
+ dealii::internal::int2type<2>)
+ {
+ const unsigned int dim = 2;
+
+ const unsigned int spacedim = DH::space_dimension;
+
+ std::vector<types::global_dof_index> dofs_on_mother;
+ std::vector<types::global_dof_index> dofs_on_children;
+
+ // loop over all lines; only on lines there can be constraints. We do
+ // so by looping over all active cells and checking whether any of
+ // the faces are refined which can only be from the neighboring cell
+ // because this one is active. In that case, the face is subject to
+ // constraints
+ //
+ // note that even though we may visit a face twice if the neighboring
+ // cells are equally refined, we can only visit each face with
+ // hanging nodes once
+ typename DH::active_cell_iterator cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+ for (; cell!=endc; ++cell)
+ // artificial cells can at best neighbor ghost cells, but we're not
+ // interested in these interfaces
+ if (!cell->is_artificial ())
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->has_children())
+ {
+ // in any case, faces can have at most two active fe
+ // indices, but here the face can have only one (namely the
+ // same as that from the cell we're sitting on), and each
+ // of the children can have only one as well. check this
+ Assert (cell->face(face)->n_active_fe_indices() == 1,
+ ExcInternalError());
+ Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
+ == true,
+ ExcInternalError());
+ for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+ if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
+ Assert (cell->face(face)->child(c)->n_active_fe_indices() == 1,
+ ExcInternalError());
+
+ // right now, all that is implemented is the case that both
+ // sides use the same fe
+ for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+ if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
+ Assert (cell->face(face)->child(c)
+ ->fe_index_is_active(cell->active_fe_index()) == true,
+ ExcNotImplemented());
+
+ // ok, start up the work
+ const FiniteElement<dim,spacedim> &fe = cell->get_fe();
+ const unsigned int fe_index = cell->active_fe_index();
+
+ const unsigned int
+ n_dofs_on_mother = 2*fe.dofs_per_vertex + fe.dofs_per_line,
+ n_dofs_on_children = fe.dofs_per_vertex + 2*fe.dofs_per_line;
+
+ dofs_on_mother.resize (n_dofs_on_mother);
+ dofs_on_children.resize (n_dofs_on_children);
+
+ Assert(n_dofs_on_mother == fe.constraints().n(),
+ ExcDimensionMismatch(n_dofs_on_mother,
+ fe.constraints().n()));
+ Assert(n_dofs_on_children == fe.constraints().m(),
+ ExcDimensionMismatch(n_dofs_on_children,
+ fe.constraints().m()));
+
+ const typename DH::line_iterator this_face = cell->face(face);
+
+ // fill the dofs indices. Use same enumeration scheme as in
+ // @p{FiniteElement::constraints()}
+ unsigned int next_index = 0;
+ for (unsigned int vertex=0; vertex<2; ++vertex)
+ for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+ dofs_on_mother[next_index++] = this_face->vertex_dof_index(vertex,dof,
+ fe_index);
+ for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
+ dofs_on_mother[next_index++] = this_face->dof_index(dof, fe_index);
+ AssertDimension (next_index, dofs_on_mother.size());
+
+ next_index = 0;
+ for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->child(0)->vertex_dof_index(1,dof,fe_index);
+ for (unsigned int child=0; child<2; ++child)
+ for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->child(child)->dof_index(dof, fe_index);
+ AssertDimension (next_index, dofs_on_children.size());
+
+ // for each row in the constraint matrix for this line:
+ for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
+ {
+ constraints.add_line (dofs_on_children[row]);
+ for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
+ constraints.add_entry (dofs_on_children[row],
+ dofs_on_mother[i],
+ fe.constraints()(row,i));
+
+ constraints.set_inhomogeneity (dofs_on_children[row], 0.);
+ }
+ }
+ else
+ {
+ // this face has no children, but it could still be that it
+ // is shared by two cells that use a different fe index.
+ // check a couple of things, but ignore the case that the
+ // neighbor is an artificial cell
+ if (!cell->at_boundary(face) &&
+ !cell->neighbor(face)->is_artificial())
+ {
+ Assert (cell->face(face)->n_active_fe_indices() == 1,
+ ExcNotImplemented());
+ Assert (cell->face(face)
+ ->fe_index_is_active(cell->active_fe_index()) == true,
+ ExcInternalError());
+ }
+ }
+ }
+
+
+
+ template <class DH>
+ void
+ make_oldstyle_hanging_node_constraints (const DH &dof_handler,
+ ConstraintMatrix &constraints,
+ dealii::internal::int2type<3>)
+ {
+ const unsigned int dim = 3;
+
+ std::vector<types::global_dof_index> dofs_on_mother;
+ std::vector<types::global_dof_index> dofs_on_children;
+
+ // loop over all quads; only on quads there can be constraints. We do
+ // so by looping over all active cells and checking whether any of
+ // the faces are refined which can only be from the neighboring cell
+ // because this one is active. In that case, the face is subject to
+ // constraints
+ //
+ // note that even though we may visit a face twice if the neighboring
+ // cells are equally refined, we can only visit each face with
+ // hanging nodes once
+ typename DH::active_cell_iterator cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+ for (; cell!=endc; ++cell)
+ // artificial cells can at best neighbor ghost cells, but we're not
+ // interested in these interfaces
+ if (!cell->is_artificial ())
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->has_children())
+ {
+ // first of all, make sure that we treat a case which is
+ // possible, i.e. either no dofs on the face at all or no
+ // anisotropic refinement
+ if (cell->get_fe().dofs_per_face == 0)
+ continue;
+
+ Assert(cell->face(face)->refinement_case()==RefinementCase<dim-1>::isotropic_refinement,
+ ExcNotImplemented());
+
+ // in any case, faces can have at most two active fe
+ // indices, but here the face can have only one (namely the
+ // same as that from the cell we're sitting on), and each
+ // of the children can have only one as well. check this
+ AssertDimension (cell->face(face)->n_active_fe_indices(), 1);
+ Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
+ == true,
+ ExcInternalError());
+ for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+ AssertDimension (cell->face(face)->child(c)->n_active_fe_indices(), 1);
+
+ // right now, all that is implemented is the case that both
+ // sides use the same fe, and not only that but also that
+ // all lines bounding this face and the children have the
+ // same fe
+ for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+ if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
+ {
+ Assert (cell->face(face)->child(c)
+ ->fe_index_is_active(cell->active_fe_index()) == true,
+ ExcNotImplemented());
+ for (unsigned int e=0; e<4; ++e)
+ {
+ Assert (cell->face(face)->child(c)->line(e)
+ ->n_active_fe_indices() == 1,
+ ExcNotImplemented());
+ Assert (cell->face(face)->child(c)->line(e)
+ ->fe_index_is_active(cell->active_fe_index()) == true,
+ ExcNotImplemented());
+ }
+ }
+ for (unsigned int e=0; e<4; ++e)
+ {
+ Assert (cell->face(face)->line(e)
+ ->n_active_fe_indices() == 1,
+ ExcNotImplemented());
+ Assert (cell->face(face)->line(e)
+ ->fe_index_is_active(cell->active_fe_index()) == true,
+ ExcNotImplemented());
+ }
+
+ // ok, start up the work
+ const FiniteElement<dim> &fe = cell->get_fe();
+ const unsigned int fe_index = cell->active_fe_index();
+
+ const unsigned int n_dofs_on_mother = fe.dofs_per_face;
+ const unsigned int n_dofs_on_children = (5*fe.dofs_per_vertex+
+ 12*fe.dofs_per_line+
+ 4*fe.dofs_per_quad);
+
+ //TODO[TL]: think about this and the following in case of anisotropic refinement
+
+ dofs_on_mother.resize (n_dofs_on_mother);
+ dofs_on_children.resize (n_dofs_on_children);
+
+ Assert(n_dofs_on_mother == fe.constraints().n(),
+ ExcDimensionMismatch(n_dofs_on_mother,
+ fe.constraints().n()));
+ Assert(n_dofs_on_children == fe.constraints().m(),
+ ExcDimensionMismatch(n_dofs_on_children,
+ fe.constraints().m()));
+
+ const typename DH::face_iterator this_face = cell->face(face);
+
+ // fill the dofs indices. Use same enumeration scheme as in
+ // @p{FiniteElement::constraints()}
+ unsigned int next_index = 0;
+ for (unsigned int vertex=0; vertex<4; ++vertex)
+ for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+ dofs_on_mother[next_index++] = this_face->vertex_dof_index(vertex,dof,
+ fe_index);
+ for (unsigned int line=0; line<4; ++line)
+ for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
+ dofs_on_mother[next_index++]
+ = this_face->line(line)->dof_index(dof, fe_index);
+ for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
+ dofs_on_mother[next_index++] = this_face->dof_index(dof, fe_index);
+ AssertDimension (next_index, dofs_on_mother.size());
+
+ next_index = 0;
+
+ // assert some consistency assumptions
+
+ //TODO[TL]: think about this in case of anisotropic
+ //refinement
+
+ Assert (dof_handler.get_tria().get_anisotropic_refinement_flag() ||
+ ((this_face->child(0)->vertex_index(3) ==
+ this_face->child(1)->vertex_index(2)) &&
+ (this_face->child(0)->vertex_index(3) ==
+ this_face->child(2)->vertex_index(1)) &&
+ (this_face->child(0)->vertex_index(3) ==
+ this_face->child(3)->vertex_index(0))),
+ ExcInternalError());
+ for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->child(0)->vertex_dof_index(3,dof);
+
+ // dof numbers on the centers of the lines bounding this
+ // face
+ for (unsigned int line=0; line<4; ++line)
+ for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->line(line)->child(0)->vertex_dof_index(1,dof, fe_index);
+
+ // next the dofs on the lines interior to the face; the
+ // order of these lines is laid down in the FiniteElement
+ // class documentation
+ for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->child(0)->line(1)->dof_index(dof, fe_index);
+ for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->child(2)->line(1)->dof_index(dof, fe_index);
+ for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->child(0)->line(3)->dof_index(dof, fe_index);
+ for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->child(1)->line(3)->dof_index(dof, fe_index);
+
+ // dofs on the bordering lines
+ for (unsigned int line=0; line<4; ++line)
+ for (unsigned int child=0; child<2; ++child)
+ for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->line(line)->child(child)->dof_index(dof, fe_index);
+
+ // finally, for the dofs interior to the four child faces
+ for (unsigned int child=0; child<4; ++child)
+ for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
+ dofs_on_children[next_index++]
+ = this_face->child(child)->dof_index(dof, fe_index);
+ AssertDimension (next_index, dofs_on_children.size());
+
+ // for each row in the constraint matrix for this line:
+ for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
+ {
+ constraints.add_line (dofs_on_children[row]);
+ for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
+ constraints.add_entry (dofs_on_children[row],
+ dofs_on_mother[i],
+ fe.constraints()(row,i));
+
+ constraints.set_inhomogeneity(dofs_on_children[row], 0.);
+ }
+ }
+ else
+ {
+ // this face has no children, but it could still be that it
+ // is shared by two cells that use a different fe index.
+ // check a couple of things, but ignore the case that the
+ // neighbor is an artificial cell
+ if (!cell->at_boundary(face) &&
+ !cell->neighbor(face)->is_artificial())
+ {
+ Assert (cell->face(face)->n_active_fe_indices() == 1,
+ ExcNotImplemented());
+ Assert (cell->face(face)
+ ->fe_index_is_active(cell->active_fe_index()) == true,
+ ExcInternalError());
+ }
+ }
+ }
+
+
+ template <class DH>
+ void
+ make_hp_hanging_node_constraints (const DH &dof_handler,
+ ConstraintMatrix &constraints)
+ {
+ // note: this function is going to be hard to understand if you
+ // haven't read the hp paper. however, we try to follow the notation
+ // laid out there, so go read the paper before you try to understand
+ // what is going on here
+
+ const unsigned int dim = DH::dimension;
+
+ const unsigned int spacedim = DH::space_dimension;
+
+
+ // a matrix to be used for constraints below. declared here and
+ // simply resized down below to avoid permanent re-allocation of
+ // memory
+ FullMatrix<double> constraint_matrix;
+
+ // similarly have arrays that will hold master and slave dof numbers,
+ // as well as a scratch array needed for the complicated case below
+ std::vector<types::global_dof_index> master_dofs;
+ std::vector<types::global_dof_index> slave_dofs;
+ std::vector<types::global_dof_index> scratch_dofs;
+
+ // caches for the face and subface interpolation matrices between
+ // different (or the same) finite elements. we compute them only
+ // once, namely the first time they are needed, and then just reuse
+ // them
+ Table<2,std_cxx1x::shared_ptr<FullMatrix<double> > >
+ face_interpolation_matrices (n_finite_elements (dof_handler),
+ n_finite_elements (dof_handler));
+ Table<3,std_cxx1x::shared_ptr<FullMatrix<double> > >
+ subface_interpolation_matrices (n_finite_elements (dof_handler),
+ n_finite_elements (dof_handler),
+ GeometryInfo<dim>::max_children_per_face);
+
+ // similarly have a cache for the matrices that are split into their
+ // master and slave parts, and for which the master part is inverted.
+ // these two matrices are derived from the face interpolation matrix
+ // as described in the @ref hp_paper "hp paper"
+ Table<2,std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > > >
+ split_face_interpolation_matrices (n_finite_elements (dof_handler),
+ n_finite_elements (dof_handler));
+
+ // finally, for each pair of finite elements, have a mask that states
+ // which of the degrees of freedom on the coarse side of a refined
+ // face will act as master dofs.
+ Table<2,std_cxx1x::shared_ptr<std::vector<bool> > >
+ master_dof_masks (n_finite_elements (dof_handler),
+ n_finite_elements (dof_handler));
+
+ // loop over all faces
+ //
+ // note that even though we may visit a face twice if the neighboring
+ // cells are equally refined, we can only visit each face with
+ // hanging nodes once
+ typename DH::active_cell_iterator cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+ for (; cell!=endc; ++cell)
+ // artificial cells can at best neighbor ghost cells, but we're not
+ // interested in these interfaces
+ if (!cell->is_artificial ())
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->has_children())
+ {
+ // first of all, make sure that we treat a case which is
+ // possible, i.e. either no dofs on the face at all or no
+ // anisotropic refinement
+ if (cell->get_fe().dofs_per_face == 0)
+ continue;
+
+ Assert(cell->face(face)->refinement_case()==RefinementCase<dim-1>::isotropic_refinement,
+ ExcNotImplemented());
+
+ // so now we've found a face of an active cell that has
+ // children. that means that there are hanging nodes here.
+
+ // in any case, faces can have at most two sets of active
+ // fe indices, but here the face can have only one (namely
+ // the same as that from the cell we're sitting on), and
+ // each of the children can have only one as well. check
+ // this
+ Assert (cell->face(face)->n_active_fe_indices() == 1,
+ ExcInternalError());
+ Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
+ == true,
+ ExcInternalError());
+ for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+ Assert (cell->face(face)->child(c)->n_active_fe_indices() == 1,
+ ExcInternalError());
+
+ // first find out whether we can constrain each of the
+ // subfaces to the mother face. in the lingo of the hp
+ // paper, this would be the simple case. note that we can
+ // short-circuit this decision if the dof_handler doesn't
+ // support hp at all
+ //
+ // ignore all interfaces with artificial cells
+ FiniteElementDomination::Domination
+ mother_face_dominates = FiniteElementDomination::either_element_can_dominate;
+
+ if (DoFHandlerSupportsDifferentFEs<DH>::value == true)
+ for (unsigned int c=0; c<cell->face(face)->number_of_children(); ++c)
+ if (!cell->neighbor_child_on_subface (face, c)->is_artificial())
+ mother_face_dominates = mother_face_dominates &
+ (cell->get_fe().compare_for_face_domination
+ (cell->neighbor_child_on_subface (face, c)->get_fe()));
+
+ switch (mother_face_dominates)
+ {
+ case FiniteElementDomination::this_element_dominates:
+ case FiniteElementDomination::either_element_can_dominate:
+ {
+ // Case 1 (the simple case and the only case that can
+ // happen for non-hp DoFHandlers): The coarse element
+ // dominates the elements on the subfaces (or they are
+ // all the same)
+ //
+ // so we are going to constrain the DoFs on the face
+ // children against the DoFs on the face itself
+ master_dofs.resize (cell->get_fe().dofs_per_face);
+
+ cell->face(face)->get_dof_indices (master_dofs,
+ cell->active_fe_index ());
+
+ // Now create constraint matrix for the subfaces and
+ // assemble it. ignore all interfaces with artificial
+ // cells because we can only get to such interfaces if
+ // the current cell is a ghost cell
+ for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+ {
+ if (cell->neighbor_child_on_subface (face, c)->is_artificial())
+ continue;
+
+ const typename DH::active_face_iterator
+ subface = cell->face(face)->child(c);
+
+ Assert (subface->n_active_fe_indices() == 1,
+ ExcInternalError());
+
+ const unsigned int
+ subface_fe_index = subface->nth_active_fe_index(0);
+
+ // we sometime run into the situation where for
+ // example on one big cell we have a FE_Q(1) and on
+ // the subfaces we have a mixture of FE_Q(1) and
+ // FE_Nothing. In that case, the face domination is
+ // either_element_can_dominate for the whole
+ // collection of subfaces, but on the particular
+ // subface between FE_Q(1) and FE_Nothing, there
+ // are no constraints that we need to take care of.
+ // in that case, just continue
+ if (cell->get_fe().compare_for_face_domination
+ (subface->get_fe(subface_fe_index))
+ ==
+ FiniteElementDomination::no_requirements)
+ continue;
+
+ // Same procedure as for the mother cell. Extract
+ // the face DoFs from the cell DoFs.
+ slave_dofs.resize (subface->get_fe(subface_fe_index)
+ .dofs_per_face);
+ subface->get_dof_indices (slave_dofs, subface_fe_index);
+
+ for (unsigned int i=0; i<slave_dofs.size(); ++i)
+ Assert (slave_dofs[i] != numbers::invalid_dof_index,
+ ExcInternalError());
+
+ // Now create the element constraint for this
+ // subface.
+ //
+ // As a side remark, one may wonder the following:
+ // neighbor_child is clearly computed correctly,
+ // i.e. taking into account face_orientation (just
+ // look at the implementation of that function).
+ // however, we don't care about this here, when we
+ // ask for subface_interpolation on subface c. the
+ // question rather is: do we have to translate 'c'
+ // here as well?
+ //
+ // the answer is in fact 'no'. if one does that,
+ // results are wrong: constraints are added twice
+ // for the same pair of nodes but with differing
+ // weights. in addition, one can look at the
+ // deal.II/project_*_03 tests that look at exactly
+ // this case: there, we have a mesh with at least
+ // one face_orientation==false and hanging nodes,
+ // and the results of those tests show that the
+ // result of projection verifies the approximation
+ // properties of a finite element onto that mesh
+ ensure_existence_of_subface_matrix
+ (cell->get_fe(),
+ subface->get_fe(subface_fe_index),
+ c,
+ subface_interpolation_matrices
+ [cell->active_fe_index()][subface_fe_index][c]);
+
+ // Add constraints to global constraint matrix.
+ filter_constraints (master_dofs,
+ slave_dofs,
+ *(subface_interpolation_matrices
+ [cell->active_fe_index()][subface_fe_index][c]),
+ constraints);
+ }
+
+ break;
+ }
+
+ case FiniteElementDomination::other_element_dominates:
+ case FiniteElementDomination::neither_element_dominates:
+ {
+ // Case 2 (the "complex" case): at least one (the
+ // neither_... case) of the finer elements or all of
+ // them (the other_... case) is dominating. See the hp
+ // paper for a way how to deal with this situation
+ //
+ // since this is something that can only happen for hp
+ // dof handlers, add a check here...
+ Assert (DoFHandlerSupportsDifferentFEs<DH>::value == true,
+ ExcInternalError());
+
+ // we first have to find the finite element that is
+ // able to generate a space that all the other ones can
+ // be constrained to
+ const unsigned int dominating_fe_index
+ = get_most_dominating_subface_fe_index (cell->face(face));
+
+ const FiniteElement<dim,spacedim> &dominating_fe
+ = dof_handler.get_fe()[dominating_fe_index];
+
+ // check also that it is able to constrain the mother
+ // face. it should be, or we wouldn't have gotten into
+ // the branch for the 'complex' case
+ Assert ((dominating_fe.compare_for_face_domination
+ (cell->face(face)->get_fe(cell->face(face)->nth_active_fe_index(0)))
+ == FiniteElementDomination::this_element_dominates)
+ ||
+ (dominating_fe.compare_for_face_domination
+ (cell->face(face)->get_fe(cell->face(face)->nth_active_fe_index(0)))
+ == FiniteElementDomination::either_element_can_dominate),
+ ExcInternalError());
+
+
+ // first get the interpolation matrix from the mother
+ // to the virtual dofs
+ Assert (dominating_fe.dofs_per_face <=
+ cell->get_fe().dofs_per_face,
+ ExcInternalError());
+
+ ensure_existence_of_face_matrix
+ (dominating_fe,
+ cell->get_fe(),
+ face_interpolation_matrices
+ [dominating_fe_index][cell->active_fe_index()]);
+
+ // split this matrix into master and slave components.
+ // invert the master component
+ ensure_existence_of_master_dof_mask
+ (cell->get_fe(),
+ dominating_fe,
+ (*face_interpolation_matrices
+ [dominating_fe_index]
+ [cell->active_fe_index()]),
+ master_dof_masks
+ [dominating_fe_index]
+ [cell->active_fe_index()]);
+
+ ensure_existence_of_split_face_matrix
+ (*face_interpolation_matrices
+ [dominating_fe_index][cell->active_fe_index()],
+ (*master_dof_masks
+ [dominating_fe_index][cell->active_fe_index()]),
+ split_face_interpolation_matrices
+ [dominating_fe_index][cell->active_fe_index()]);
+
+ const FullMatrix<double> &restrict_mother_to_virtual_master_inv
+ = (split_face_interpolation_matrices
+ [dominating_fe_index][cell->active_fe_index()]->first);
+
+ const FullMatrix<double> &restrict_mother_to_virtual_slave
+ = (split_face_interpolation_matrices
+ [dominating_fe_index][cell->active_fe_index()]->second);
+
+ // now compute the constraint matrix as the product
+ // between the inverse matrix and the slave part
+ constraint_matrix.reinit (cell->get_fe().dofs_per_face -
+ dominating_fe.dofs_per_face,
+ dominating_fe.dofs_per_face);
+ restrict_mother_to_virtual_slave
+ .mmult (constraint_matrix,
+ restrict_mother_to_virtual_master_inv);
+
+ // then figure out the global numbers of master and
+ // slave dofs and apply constraints
+ scratch_dofs.resize (cell->get_fe().dofs_per_face);
+ cell->face(face)->get_dof_indices (scratch_dofs,
+ cell->active_fe_index ());
+
+ // split dofs into master and slave components
+ master_dofs.clear ();
+ slave_dofs.clear ();
+ for (unsigned int i=0; i<cell->get_fe().dofs_per_face; ++i)
+ if ((*master_dof_masks
+ [dominating_fe_index][cell->active_fe_index()])[i] == true)
+ master_dofs.push_back (scratch_dofs[i]);
+ else
+ slave_dofs.push_back (scratch_dofs[i]);
+
+ AssertDimension (master_dofs.size(), dominating_fe.dofs_per_face);
+ AssertDimension (slave_dofs.size(),
+ cell->get_fe().dofs_per_face - dominating_fe.dofs_per_face);
+
+ filter_constraints (master_dofs,
+ slave_dofs,
+ constraint_matrix,
+ constraints);
+
+
+
+ // next we have to deal with the subfaces. do as
+ // discussed in the hp paper
+ for (unsigned int sf=0;
+ sf<cell->face(face)->n_children(); ++sf)
+ {
+ // ignore interfaces with artificial cells as well
+ // as interfaces between ghost cells in 2d
+ if (cell->neighbor_child_on_subface (face, sf)->is_artificial()
+ ||
+ (dim==2 && cell->is_ghost()
+ &&
+ cell->neighbor_child_on_subface (face, sf)->is_ghost()))
+ continue;
+
+ Assert (cell->face(face)->child(sf)
+ ->n_active_fe_indices() == 1,
+ ExcInternalError());
+
+ const unsigned int subface_fe_index
+ = cell->face(face)->child(sf)->nth_active_fe_index(0);
+ const FiniteElement<dim,spacedim> &subface_fe
+ = dof_handler.get_fe()[subface_fe_index];
+
+ // first get the interpolation matrix from the
+ // subface to the virtual dofs
+ Assert (dominating_fe.dofs_per_face <=
+ subface_fe.dofs_per_face,
+ ExcInternalError());
+ ensure_existence_of_subface_matrix
+ (dominating_fe,
+ subface_fe,
+ sf,
+ subface_interpolation_matrices
+ [dominating_fe_index][subface_fe_index][sf]);
+
+ const FullMatrix<double> &restrict_subface_to_virtual
+ = *(subface_interpolation_matrices
+ [dominating_fe_index][subface_fe_index][sf]);
+
+ constraint_matrix.reinit (subface_fe.dofs_per_face,
+ dominating_fe.dofs_per_face);
+
+ restrict_subface_to_virtual
+ .mmult (constraint_matrix,
+ restrict_mother_to_virtual_master_inv);
+
+ slave_dofs.resize (subface_fe.dofs_per_face);
+ cell->face(face)->child(sf)->get_dof_indices (slave_dofs,
+ subface_fe_index);
+
+ filter_constraints (master_dofs,
+ slave_dofs,
+ constraint_matrix,
+ constraints);
+ }
+
+ break;
+ }
+
+ case FiniteElementDomination::no_requirements:
+ // there are no continuity requirements between the two
+ // elements. record no constraints
+ break;
+
+ default:
+ // we shouldn't get here
+ Assert (false, ExcInternalError());
+ }
+ }
+ else
+ {
+ // this face has no children, but it could still be that it
+ // is shared by two cells that use a different fe index
+ Assert (cell->face(face)
+ ->fe_index_is_active(cell->active_fe_index()) == true,
+ ExcInternalError());
+
+ // see if there is a neighbor that is an artificial cell.
+ // in that case, we're not interested in this interface. we
+ // test this case first since artificial cells may not have
+ // an active_fe_index set, etc
+ if (!cell->at_boundary(face)
+ &&
+ cell->neighbor(face)->is_artificial())
+ continue;
+
+ // Only if there is a neighbor with a different
+ // active_fe_index and the same h-level, some action has to
+ // be taken.
+ if ((DoFHandlerSupportsDifferentFEs<DH>::value == true)
+ &&
+ !cell->face(face)->at_boundary ()
+ &&
+ (cell->neighbor(face)->active_fe_index () !=
+ cell->active_fe_index ())
+ &&
+ (!cell->face(face)->has_children() &&
+ !cell->neighbor_is_coarser(face) ))
+ {
+ const typename DH::level_cell_iterator neighbor = cell->neighbor (face);
+
+ // see which side of the face we have to constrain
+ switch (cell->get_fe().compare_for_face_domination (neighbor->get_fe ()))
+ {
+ case FiniteElementDomination::this_element_dominates:
+ {
+ // Get DoFs on dominating and dominated side of the
+ // face
+ master_dofs.resize (cell->get_fe().dofs_per_face);
+ cell->face(face)->get_dof_indices (master_dofs,
+ cell->active_fe_index ());
+
+ slave_dofs.resize (neighbor->get_fe().dofs_per_face);
+ cell->face(face)->get_dof_indices (slave_dofs,
+ neighbor->active_fe_index ());
+
+ // break if the n_master_dofs == 0, because we are
+ // attempting to constrain to an element that has
+ // no face dofs
+ if (master_dofs.size() == 0) break;
+
+ // make sure the element constraints for this face
+ // are available
+ ensure_existence_of_face_matrix
+ (cell->get_fe(),
+ neighbor->get_fe(),
+ face_interpolation_matrices
+ [cell->active_fe_index()][neighbor->active_fe_index()]);
+
+ // Add constraints to global constraint matrix.
+ filter_constraints (master_dofs,
+ slave_dofs,
+ *(face_interpolation_matrices
+ [cell->active_fe_index()]
+ [neighbor->active_fe_index()]),
+ constraints);
+
+ break;
+ }
+
+ case FiniteElementDomination::other_element_dominates:
+ {
+ // we don't do anything here since we will come
+ // back to this face from the other cell, at which
+ // time we will fall into the first case clause
+ // above
+ break;
+ }
+
+ case FiniteElementDomination::either_element_can_dominate:
+ {
+ // it appears as if neither element has any
+ // constraints on its neighbor. this may be because
+ // neither element has any DoFs on faces at all. or
+ // that the two elements are actually the same,
+ // although they happen to run under different
+ // fe_indices (this is what happens in
+ // hp/hp_hanging_nodes_01 for example).
+ //
+ // another possibility is what happens in crash_13.
+ // there, we have FESystem(FE_Q(1),FE_DGQ(0)) vs.
+ // FESystem(FE_Q(1),FE_DGQ(1)). neither of them
+ // 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;
+ }
+
+ case FiniteElementDomination::neither_element_dominates:
+ {
+ // we don't presently know what exactly to do here.
+ // it isn't quite clear what exactly we would have
+ // to do here. sit tight until someone trips over
+ // the following statement and see what exactly is
+ // going on
+ Assert (false, ExcNotImplemented());
+ break;
+ }
+
+ case FiniteElementDomination::no_requirements:
+ {
+ // nothing to do here
+ break;
+ }
+
+ default:
+ // we shouldn't get here
+ Assert (false, ExcInternalError());
+ }
+ }
+ }
+ }
+ }
+
+
+
+
+ template <class DH>
+ void
+ make_hanging_node_constraints (const DH &dof_handler,
+ ConstraintMatrix &constraints)
+ {
+ // Decide whether to use the new or old make_hanging_node_constraints
+ // function. If all the FiniteElement or all elements in a FECollection
+ // support the new face constraint matrix, the new code will be used.
+ // Otherwise, the old implementation is used for the moment.
+ if (dof_handler.get_fe().hp_constraints_are_implemented ())
+ internal::
+ make_hp_hanging_node_constraints (dof_handler,
+ constraints);
+ else
+ internal::
+ make_oldstyle_hanging_node_constraints (dof_handler,
+ constraints,
+ dealii::internal::int2type<DH::dimension>());
+ }
+
+
+
+ namespace
+ {
+ // enter constraints for periodicity into the given ConstraintMatrix object.
+ // this function is called when at least one of the two face iterators corresponds
+ // to an active object without further children
+ //
+ // @param transformation A matrix that maps degrees of freedom from one face
+ // to another. If the DoFs on the two faces are supposed to match exactly, then
+ // the matrix so provided will be the identity matrix. if face 2 is once refined
+ // from face 1, then the matrix needs to be the interpolation matrix from a face
+ // 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 <typename FaceIterator>
+ void
+ set_periodicity_constraints (const FaceIterator &face_1,
+ const typename identity<FaceIterator>::type &face_2,
+ const FullMatrix<double> &transformation,
+ dealii::ConstraintMatrix &constraint_matrix,
+ const ComponentMask &component_mask,
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
+ {
+ static const int dim = FaceIterator::AccessorType::dimension;
+ static const int spacedim = FaceIterator::AccessorType::space_dimension;
+
+ // we should be in the case where face_1 is active, i.e. has no children:
+ Assert (!face_1->has_children(),
+ ExcInternalError());
+
+ Assert (face_1->n_active_fe_indices() == 1,
+ ExcInternalError());
+
+ // if face_2 does have children, then we need to iterate over them
+ if (face_2->has_children())
+ {
+ Assert (face_2->n_children() == GeometryInfo<dim>::max_children_per_face,
+ ExcNotImplemented());
+ const unsigned int dofs_per_face
+ = face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face;
+ FullMatrix<double> child_transformation (dofs_per_face, dofs_per_face);
+ FullMatrix<double> subface_interpolation (dofs_per_face, dofs_per_face);
+ for (unsigned int c=0; c<face_2->n_children(); ++c)
+ {
+ // get the interpolation matrix recursively from the one that
+ // interpolated from face_1 to face_2 by multiplying from the
+ // left with the one that interpolates from face_2 to
+ // its child
+ face_1->get_fe(face_1->nth_active_fe_index(0))
+ .get_subface_interpolation_matrix (face_1->get_fe(face_1->nth_active_fe_index(0)),
+ c,
+ subface_interpolation);
+ subface_interpolation.mmult (child_transformation, transformation);
+ set_periodicity_constraints(face_1, face_2->child(c),
+ child_transformation,
+ constraint_matrix, component_mask,
+ face_orientation, face_flip, face_rotation);
+ }
+ }
+ else
+ // both faces are active. we need to match the corresponding DoFs of both faces
+ {
+ const unsigned int face_1_index = face_1->nth_active_fe_index(0);
+ const unsigned int face_2_index = face_2->nth_active_fe_index(0);
+ Assert(face_1->get_fe(face_1_index) == face_2->get_fe(face_1_index),
+ ExcMessage ("Matching periodic cells need to use the same finite element"));
+
+ const FiniteElement<dim, spacedim> &fe = face_1->get_fe(face_1_index);
+
+ Assert(component_mask.represents_n_components(fe.n_components()),
+ ExcMessage ("The number of components in the mask has to be either "
+ "zero or equal to the number of components in the finite " "element."));
+
+ const unsigned int dofs_per_face = fe.dofs_per_face;
+
+ std::vector<types::global_dof_index> dofs_1(dofs_per_face);
+ std::vector<types::global_dof_index> dofs_2(dofs_per_face);
+
+ face_1->get_dof_indices(dofs_1, face_1_index);
+ face_2->get_dof_indices(dofs_2, face_2_index);
+
+ // Well, this is a hack:
+ //
+ // There is no
+ // face_to_face_index(face_index,
+ // face_orientation,
+ // face_flip,
+ // face_rotation)
+ // function in FiniteElementData, so we have to use
+ // face_to_cell_index(face_index, face
+ // face_orientation,
+ // face_flip,
+ // face_rotation)
+ // But this will give us an index on a cell - something we cannot work
+ // with directly. But luckily we can match them back :-]
+
+ std::map<unsigned int, unsigned int> cell_to_rotated_face_index;
+
+ // Build up a cell to face index for face_2:
+ for (unsigned int i = 0; i < dofs_per_face; ++i)
+ {
+ const unsigned int cell_index = fe.face_to_cell_index(i, 0, /* It doesn't really matter, just assume
+ * we're on the first face...
+ */
+ true, false, false // default orientation
+ );
+ cell_to_rotated_face_index[cell_index] = i;
+ }
+
+ // loop over all dofs on face 2 and constrain them again the ones on face 1
+ for (unsigned int i=0; i<dofs_per_face; ++i)
+ if (!constraint_matrix.is_constrained(dofs_2[i]))
+ if ((component_mask.n_selected_components(fe.n_components())
+ == fe.n_components())
+ ||
+ component_mask[fe.face_system_to_component_index(i).first])
+ {
+ // 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<dofs_per_face; ++jj)
+ if (((transformation(i,jj) == 0) || (transformation(i,jj) == 1)) == false)
+ {
+ is_identity_constrained = false;
+ break;
+ }
+ unsigned int identity_constraint_target = numbers::invalid_unsigned_int;
+ if (is_identity_constrained == true)
+ {
+ bool one_identity_found = false;
+ for (unsigned int jj=0; jj<dofs_per_face; ++jj)
+ if (transformation(i,jj) == 1)
+ {
+ if (one_identity_found == false)
+ {
+ one_identity_found = true;
+ identity_constraint_target = jj;
+ }
+ else
+ {
+ is_identity_constrained = false;
+ identity_constraint_target = numbers::invalid_unsigned_int;
+ break;
+ }
+ }
+ }
+
+ // now treat constraints, either as an equality constraint or
+ // as a sequence of constraints
+ if (is_identity_constrained == true)
+ {
+ // Query the correct face_index on face_2 respecting the given
+ // orientation:
+ const unsigned int j =
+ cell_to_rotated_face_index[fe.face_to_cell_index(identity_constraint_target,
+ 0, /* It doesn't really matter, just assume
+ * we're on the first face...
+ */
+ face_orientation, face_flip, face_rotation)];
+
+ // if the two aren't already identity constrained (whichever way
+ // around, then enter the constraint. otherwise there is nothing
+ // for us still to do
+ if (constraint_matrix.are_identity_constrained(dofs_2[i], dofs_1[i]) == false)
+ {
+ constraint_matrix.add_line(dofs_2[i]);
+ constraint_matrix.add_entry(dofs_2[i], dofs_1[j], 1);
+ }
+ }
+ else
+ {
+ // this is just a regular constraint. enter it piece by piece
+ constraint_matrix.add_line(dofs_2[i]);
+ for (unsigned int jj=0; jj<dofs_per_face; ++jj)
+ {
+ // Query the correct face_index on face_2 respecting the given
+ // orientation:
+ const unsigned int j =
+ cell_to_rotated_face_index[fe.face_to_cell_index(jj, 0, /* It doesn't really matter, just assume
+ * we're on the first face...
+ */
+ face_orientation, face_flip, face_rotation)];
+
+ // And finally constrain the two DoFs respecting component_mask:
+ if (transformation(i,jj) != 0)
+ constraint_matrix.add_entry(dofs_2[i], dofs_1[j],
+ transformation(i,jj));
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ template <typename FaceIterator>
+ void
+ make_periodicity_constraints (const FaceIterator &face_1,
+ const typename identity<FaceIterator>::type &face_2,
+ dealii::ConstraintMatrix &constraint_matrix,
+ const ComponentMask &component_mask,
+ const bool face_orientation,
+ const bool face_flip,
+ const bool face_rotation)
+ {
+ static const int dim = FaceIterator::AccessorType::dimension;
+
+ Assert( (dim != 1) ||
+ (face_orientation == true &&
+ face_flip == false &&
+ face_rotation == false),
+ ExcMessage ("The supplied orientation "
+ "(face_orientation, face_flip, face_rotation) "
+ "is invalid for 1D"));
+
+ Assert( (dim != 2) ||
+ (face_orientation == true &&
+ face_rotation == false),
+ ExcMessage ("The supplied orientation "
+ "(face_orientation, face_flip, face_rotation) "
+ "is invalid for 2D"));
+
+ Assert(face_1 != face_2,
+ ExcMessage ("face_1 and face_2 are equal! Cannot constrain DoFs "
+ "on the very same face"));
+
+ Assert(face_1->at_boundary() && face_2->at_boundary(),
+ ExcMessage ("Faces for periodicity constraints must be on the boundary"));
+
+
+ // A lookup table on how to go through the child faces depending on the
+ // orientation:
+
+ static const int lookup_table_2d[2][2] =
+ {
+ // flip:
+ {0, 1}, // false
+ {1, 0}, // true
+ };
+
+ static const int lookup_table_3d[2][2][2][4] =
+ {
+ // orientation flip rotation
+ { { {0, 2, 1, 3}, // false false false
+ {2, 3, 0, 1}, // false false true
+ },
+ { {3, 1, 2, 0}, // false true false
+ {1, 0, 3, 2}, // false true true
+ },
+ },
+ { { {0, 1, 2, 3}, // true false false
+ {1, 3, 0, 2}, // true false true
+ },
+ { {3, 2, 1, 0}, // true true false
+ {2, 0, 3, 1}, // true true true
+ },
+ },
+ };
+
+ // In the case that both faces have children, we loop over all
+ // children and apply make_periodicty_constrains recursively:
+ if (face_1->has_children() && face_2->has_children())
+ {
+ Assert(face_1->n_children() == GeometryInfo<dim>::max_children_per_face &&
+ face_2->n_children() == GeometryInfo<dim>::max_children_per_face,
+ ExcNotImplemented());
+
+ for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face; ++i)
+ {
+ // Lookup the index for the second face
+ unsigned int j;
+ switch (dim)
+ {
+ case 2:
+ j = lookup_table_2d[face_flip][i];
+ break;
+ case 3:
+ j = lookup_table_3d[face_orientation][face_flip][face_rotation][i];
+ break;
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+
+ make_periodicity_constraints (face_1->child(i),
+ face_2->child(j),
+ constraint_matrix,
+ component_mask,
+ face_orientation,
+ face_flip,
+ face_rotation);
+ }
+ }
+ else
+ // otherwise at least one of the two faces is active and
+ // we need to enter the constraints
+ {
+ if (face_2->has_children() == false)
+ set_periodicity_constraints(face_2, face_1,
+ FullMatrix<double>(IdentityMatrix(face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face)),
+ constraint_matrix,
+ component_mask,
+ face_orientation, face_flip, face_rotation);
+ else
+ set_periodicity_constraints(face_1, face_2,
+ FullMatrix<double>(IdentityMatrix(face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face)),
+ constraint_matrix,
+ component_mask,
+ face_orientation, face_flip, face_rotation);
+ }
+ }
+
+
+
+ template<typename DH>
+ void
+ make_periodicity_constraints (const DH &dof_handler,
+ const types::boundary_id b_id1,
+ const types::boundary_id b_id2,
+ const int direction,
+ dealii::ConstraintMatrix &constraint_matrix,
+ const ComponentMask &component_mask)
+ {
+ Tensor<1,DH::space_dimension> dummy;
+ make_periodicity_constraints (dof_handler,
+ b_id1,
+ b_id2,
+ direction,
+ dummy,
+ constraint_matrix,
+ component_mask);
+ }
+
+
+
+ template<typename DH>
+ void
+ make_periodicity_constraints (const DH &dof_handler,
+ const types::boundary_id b_id1,
+ const types::boundary_id b_id2,
+ const int direction,
+ dealii::Tensor<1,DH::space_dimension> &offset,
+ dealii::ConstraintMatrix &constraint_matrix,
+ const ComponentMask &component_mask)
+ {
+ static const int space_dim = DH::space_dimension;
+ Assert (0<=direction && direction<space_dim,
+ ExcIndexRange (direction, 0, space_dim));
+
+#if defined(DEBUG) && defined(DEAL_II_WITH_P4EST)
+ // Check whether we run on a non parallel mesh or on a
+ // parallel::distributed::Triangulation in serial
+ {
+ typedef parallel::distributed::Triangulation<DH::dimension,DH::space_dimension> PTRIA;
+ const PTRIA *ptria_p = dynamic_cast<const PTRIA *> (&dof_handler.get_tria());
+ Assert ((ptria_p == 0 || Utilities::MPI::n_mpi_processes(ptria_p->get_communicator()) == 1),
+ ExcMessage ("This function can not be used with distributed triangulations."
+ "See the documentation for more information."));
+ }
+#endif
+
+ Assert (b_id1 != b_id2,
+ ExcMessage ("The boundary indicators b_id1 and b_id2 must be"
+ "different to denote different boundaries."));
+
+ typedef typename DH::face_iterator FaceIterator;
+ typedef std::map<FaceIterator, std::pair<FaceIterator, std::bitset<3> > > FaceMap;
+
+ // Collect matching periodic cells on the coarsest level:
+ FaceMap matched_cells =
+ GridTools::collect_periodic_face_pairs(dof_handler,
+ b_id1, b_id2,
+ direction, offset);
+
+ // And apply the low level make_periodicity_constraints function to
+ // every matching pair:
+ for (typename FaceMap::iterator it = matched_cells.begin();
+ it != matched_cells.end(); ++it)
+ {
+ typedef typename DH::face_iterator FaceIterator;
+ const FaceIterator &face_1 = it->first;
+ const FaceIterator &face_2 = it->second.first;
+ const std::bitset<3> &orientation = it->second.second;
+
+ Assert(face_1->at_boundary() && face_2->at_boundary(),
+ ExcInternalError());
+
+ Assert (face_1->boundary_indicator() == b_id1 &&
+ face_2->boundary_indicator() == b_id2,
+ ExcInternalError());
+
+ Assert (face_1 != face_2,
+ ExcInternalError());
+
+ make_periodicity_constraints(face_1,
+ face_2,
+ constraint_matrix,
+ component_mask,
+ orientation[0],
+ orientation[1],
+ orientation[2]);
+ }
+ }
+
+
+
+ template<typename DH>
+ void
+ make_periodicity_constraints (const DH &dof_handler,
+ const types::boundary_id b_id,
+ const int direction,
+ dealii::ConstraintMatrix &constraint_matrix,
+ const ComponentMask &component_mask)
+ {
+ Tensor<1,DH::space_dimension> dummy;
+ make_periodicity_constraints (dof_handler,
+ b_id,
+ direction,
+ dummy,
+ constraint_matrix,
+ component_mask);
+ }
+
+
+
+ template<typename DH>
+ void
+ make_periodicity_constraints (const DH &dof_handler,
+ const types::boundary_id b_id,
+ const int direction,
+ dealii::Tensor<1,DH::space_dimension> &offset,
+ dealii::ConstraintMatrix &constraint_matrix,
+ const ComponentMask &component_mask)
+ {
+ static const int dim = DH::dimension;
+ static const int space_dim = DH::space_dimension;
+
+ Assert (0<=direction && direction<space_dim,
+ ExcIndexRange (direction, 0, space_dim));
+
+ Assert(dim == space_dim,
+ ExcNotImplemented());
+
+#if defined(DEBUG) && defined(DEAL_II_WITH_P4EST)
+ // Check whether we run on a non parallel mesh or on a
+ // parallel::distributed::Triangulation in serial
+ {
+ typedef typename parallel::distributed::Triangulation<DH::dimension,DH::space_dimension> PTRIA;
+ const PTRIA *ptria_p = dynamic_cast<const PTRIA *> (&dof_handler.get_tria());
+ Assert ((ptria_p == 0 || Utilities::MPI::n_mpi_processes(ptria_p->get_communicator()) == 1),
+ ExcMessage ("This function can not be used with distributed triangulations."
+ "See the documentation for more information."));
+ }
+#endif
+
+ typedef typename DH::face_iterator FaceIterator;
+ typedef std::map<FaceIterator, FaceIterator> FaceMap;
+
+ // Collect matching periodic cells on the coarsest level:
+ FaceMap matched_cells =
+ GridTools::collect_periodic_face_pairs(dof_handler,
+ b_id,
+ direction, offset);
+
+ // And apply the low level make_periodicity_constraints function to
+ // every matching pair:
+ for (typename FaceMap::iterator it = matched_cells.begin();
+ it != matched_cells.end(); ++it)
+ {
+ typedef typename DH::face_iterator FaceIterator;
+ const FaceIterator &face_1 = it->first;
+ const FaceIterator &face_2 = it->second;
+
+ Assert(face_1->at_boundary() && face_2->at_boundary(),
+ ExcInternalError());
+
+ Assert (face_1->boundary_indicator() == b_id &&
+ face_2->boundary_indicator() == b_id,
+ ExcInternalError());
+
+ Assert (face_1 != face_2,
+ ExcInternalError());
+
+ make_periodicity_constraints(face_1,
+ face_2,
+ constraint_matrix,
+ component_mask
+ /* standard orientation */);
+ }
+ }
+
+
+
+ namespace internal
+ {
+ namespace
+ {
+ /**
+ * This is a function that is called by the _2 function and that
+ * operates on a range of cells only. It is used to split up the
+ * whole range of cells into chunks which are then worked on in
+ * parallel, if multithreading is available.
+ */
+ template <int dim, int spacedim>
+ void
+ compute_intergrid_weights_3 (
+ const dealii::DoFHandler<dim,spacedim> &coarse_grid,
+ const unsigned int coarse_component,
+ const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+ const std::vector<dealii::Vector<double> > ¶meter_dofs,
+ const std::vector<types::global_dof_index> &weight_mapping,
+ std::vector<std::map<types::global_dof_index, float> > &weights,
+ const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &begin,
+ const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &end)
+ {
+ // aliases to the finite elements used by the dof handlers:
+ const FiniteElement<dim,spacedim> &coarse_fe = coarse_grid.get_fe();
+
+ // for each cell on the parameter grid: find out which degrees of
+ // freedom on the fine grid correspond in which way to the degrees
+ // of freedom on the parameter grid
+ //
+ // since for continuous FEs some dofs exist on more than one cell,
+ // we have to track which ones were already visited. the problem is
+ // that if we visit a dof first on one cell and compute its weight
+ // with respect to some global dofs to be non-zero, and later visit
+ // the dof again on another cell and (since we are on another cell)
+ // recompute the weights with respect to the same dofs as above to
+ // be zero now, we have to preserve them. we therefore overwrite
+ // all weights if they are nonzero and do not enforce zero weights
+ // since that might be only due to the fact that we are on another
+ // cell.
+ //
+ // example:
+ // coarse grid
+ // | | |
+ // *-----*-----*
+ // | cell|cell |
+ // | 1 | 2 |
+ // | | |
+ // 0-----1-----*
+ //
+ // fine grid
+ // | | | | |
+ // *--*--*--*--*
+ // | | | | |
+ // *--*--*--*--*
+ // | | | | |
+ // *--x--y--*--*
+ //
+ // when on cell 1, we compute the weights of dof 'x' to be 1/2 from
+ // parameter dofs 0 and 1, respectively. however, when later we are
+ // on cell 2, we again compute the prolongation of shape function 1
+ // restricted to cell 2 to the globla grid and find that the weight
+ // of global dof 'x' now is zero. however, we should not overwrite
+ // the old value.
+ //
+ // we therefore always only set nonzero values. why adding up is
+ // not useful: dof 'y' would get weight 1 from parameter dof 1 on
+ // both cells 1 and 2, but the correct weight is nevertheless only
+ // 1.
+
+ // vector to hold the representation of a single degree of freedom
+ // on the coarse grid (for the selected fe) on the fine grid
+ const types::global_dof_index n_fine_dofs = weight_mapping.size();
+ dealii::Vector<double> global_parameter_representation (n_fine_dofs);
+
+ typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator cell;
+ std::vector<types::global_dof_index> parameter_dof_indices (coarse_fe.dofs_per_cell);
+
+ for (cell=begin; cell!=end; ++cell)
+ {
+ // get the global indices of the parameter dofs on this
+ // parameter grid cell
+ cell->get_dof_indices (parameter_dof_indices);
+
+ // loop over all dofs on this cell and check whether they are
+ // interesting for us
+ for (unsigned int local_dof=0;
+ local_dof<coarse_fe.dofs_per_cell;
+ ++local_dof)
+ if (coarse_fe.system_to_component_index(local_dof).first
+ ==
+ coarse_component)
+ {
+ // the how-many-th parameter is this on this cell?
+ const unsigned int local_parameter_dof
+ = coarse_fe.system_to_component_index(local_dof).second;
+
+ global_parameter_representation = 0;
+
+ // distribute the representation of
+ // @p{local_parameter_dof} on the parameter grid cell
+ // @p{cell} to the global data space
+ coarse_to_fine_grid_map[cell]->
+ set_dof_values_by_interpolation (parameter_dofs[local_parameter_dof],
+ global_parameter_representation);
+ // now that we've got the global representation of each
+ // parameter dof, we've only got to clobber the non-zero
+ // entries in that vector and store the result
+ //
+ // what we have learned: if entry @p{i} of the global
+ // vector holds the value @p{v[i]}, then this is the
+ // weight with which the present dof contributes to
+ // @p{i}. there may be several such @p{i}s and their
+ // weights' sum should be one. Then, @p{v[i]} should be
+ // equal to @p{\sum_j w_{ij} p[j]} with @p{p[j]} be the
+ // values of the degrees of freedom on the coarse grid.
+ // we can thus compute constraints which link the degrees
+ // of freedom @p{v[i]} on the fine grid to those on the
+ // coarse grid, @p{p[j]}. Now to use these as real
+ // constraints, rather than as additional equations, we
+ // have to identify representants among the @p{i} for
+ // each @p{j}. this will be done by simply taking the
+ // first @p{i} for which @p{w_{ij}==1}.
+ //
+ // guard modification of the weights array by a Mutex.
+ // since it should happen rather rarely that there are
+ // several threads operating on different intergrid
+ // weights, have only one mutex for all of them
+ static Threads::Mutex mutex;
+ Threads::Mutex::ScopedLock lock (mutex);
+ for (types::global_dof_index i=0; i<global_parameter_representation.size(); ++i)
+ // set this weight if it belongs to a parameter dof.
+ if (weight_mapping[i] != numbers::invalid_dof_index)
+ {
+ // only overwrite old value if not by zero
+ if (global_parameter_representation(i) != 0)
+ {
+ const types::global_dof_index wi = parameter_dof_indices[local_dof],
+ wj = weight_mapping[i];
+ weights[wi][wj] = global_parameter_representation(i);
+ };
+ }
+ else
+ Assert (global_parameter_representation(i) == 0,
+ ExcInternalError());
+ }
+ }
+ }
+
+
+ /**
+ * This is a helper function that is used in the computation of
+ * integrid constraints. See the function for a thorough description
+ * of how it works.
+ */
+ template <int dim, int spacedim>
+ void
+ compute_intergrid_weights_2 (
+ const dealii::DoFHandler<dim,spacedim> &coarse_grid,
+ const unsigned int coarse_component,
+ const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+ const std::vector<dealii::Vector<double> > ¶meter_dofs,
+ const std::vector<types::global_dof_index> &weight_mapping,
+ std::vector<std::map<types::global_dof_index,float> > &weights)
+ {
+ // simply distribute the range of cells to different threads
+ typedef typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator active_cell_iterator;
+ std::vector<std::pair<active_cell_iterator,active_cell_iterator> >
+ cell_intervals = Threads::split_range<active_cell_iterator> (coarse_grid.begin_active(),
+ coarse_grid.end(),
+ multithread_info.n_default_threads);
+
+ // TODO: use WorkStream here
+
+ Threads::TaskGroup<> tasks;
+ void (*fun_ptr) (const dealii::DoFHandler<dim,spacedim> &,
+ const unsigned int ,
+ const InterGridMap<dealii::DoFHandler<dim,spacedim> > &,
+ const std::vector<dealii::Vector<double> > &,
+ const std::vector<types::global_dof_index> &,
+ std::vector<std::map<types::global_dof_index, float> > &,
+ const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &,
+ const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &)
+ = &compute_intergrid_weights_3<dim>;
+ for (unsigned int i=0; i<multithread_info.n_default_threads; ++i)
+ tasks += Threads::new_task (fun_ptr,
+ coarse_grid, coarse_component,
+ coarse_to_fine_grid_map, parameter_dofs,
+ weight_mapping, weights,
+ cell_intervals[i].first,
+ cell_intervals[i].second);
+
+ // wait for the tasks to finish
+ tasks.join_all ();
+ }
+
+
+
+ /**
+ * This is a helper function that is used in the computation of
+ * integrid constraints. See the function for a thorough description
+ * of how it works.
+ */
+ template <int dim, int spacedim>
+ unsigned int
+ compute_intergrid_weights_1 (
+ const dealii::DoFHandler<dim,spacedim> &coarse_grid,
+ const unsigned int coarse_component,
+ const dealii::DoFHandler<dim,spacedim> &fine_grid,
+ const unsigned int fine_component,
+ const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+ std::vector<std::map<types::global_dof_index, float> > &weights,
+ std::vector<types::global_dof_index> &weight_mapping)
+ {
+ // aliases to the finite elements used by the dof handlers:
+ const FiniteElement<dim,spacedim> &coarse_fe = coarse_grid.get_fe(),
+ &fine_fe = fine_grid.get_fe();
+
+ // global numbers of dofs
+ const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs(),
+ n_fine_dofs = fine_grid.n_dofs();
+
+ // local numbers of dofs
+ const unsigned int fine_dofs_per_cell = fine_fe.dofs_per_cell;
+
+ // alias the number of dofs per cell belonging to the
+ // coarse_component which is to be the restriction of the fine
+ // grid:
+ const unsigned int coarse_dofs_per_cell_component
+ = coarse_fe.base_element(coarse_fe.component_to_base_index(coarse_component).first).dofs_per_cell;
+
+
+ // Try to find out whether the grids stem from the same coarse
+ // grid. This is a rather crude test, but better than nothing
+ Assert (coarse_grid.get_tria().n_cells(0) == fine_grid.get_tria().n_cells(0),
+ ExcGridsDontMatch());
+
+ // check whether the map correlates the right objects
+ Assert (&coarse_to_fine_grid_map.get_source_grid() == &coarse_grid,
+ ExcGridsDontMatch ());
+ Assert (&coarse_to_fine_grid_map.get_destination_grid() == &fine_grid,
+ ExcGridsDontMatch ());
+
+
+ // check whether component numbers are valid
+ AssertIndexRange (coarse_component,coarse_fe.n_components());
+ AssertIndexRange (fine_component, fine_fe.n_components());
+
+ // check whether respective finite elements are equal
+ Assert (coarse_fe.base_element (coarse_fe.component_to_base_index(coarse_component).first)
+ ==
+ fine_fe.base_element (fine_fe.component_to_base_index(fine_component).first),
+ ExcFiniteElementsDontMatch());
+
+#ifdef DEBUG
+ // if in debug mode, check whether the coarse grid is indeed
+ // coarser everywhere than the fine grid
+ for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
+ cell=coarse_grid.begin_active();
+ cell != coarse_grid.end(); ++cell)
+ Assert (cell->level() <= coarse_to_fine_grid_map[cell]->level(),
+ ExcGridNotCoarser());
+#endif
+
+ /*
+ * From here on: the term `parameter' refers to the selected
+ * component on the coarse grid and its analogon on the fine grid.
+ * The naming of variables containing this term is due to the fact
+ * that `selected_component' is longer, but also due to the fact
+ * that the code of this function was initially written for a
+ * program where the component which we wanted to match between
+ * grids was actually the `parameter' variable.
+ *
+ * Likewise, the terms `parameter grid' and `state grid' refer to
+ * the coarse and fine grids, respectively.
+ *
+ * Changing the names of variables would in principle be a good
+ * idea, but would not make things simpler and would be another
+ * source of errors. If anyone feels like doing so: patches would
+ * be welcome!
+ */
+
+
+
+ // set up vectors of cell-local data; each vector represents one
+ // degree of freedom of the coarse-grid variable in the fine-grid
+ // element
+ std::vector<dealii::Vector<double> >
+ parameter_dofs (coarse_dofs_per_cell_component,
+ dealii::Vector<double>(fine_dofs_per_cell));
+ // for each coarse dof: find its position within the fine element
+ // and set this value to one in the respective vector (all other
+ // values are zero by construction)
+ for (unsigned int local_coarse_dof=0;
+ local_coarse_dof<coarse_dofs_per_cell_component;
+ ++local_coarse_dof)
+ for (unsigned int fine_dof=0; fine_dof<fine_fe.dofs_per_cell; ++fine_dof)
+ if (fine_fe.system_to_component_index(fine_dof)
+ ==
+ std::make_pair (fine_component, local_coarse_dof))
+ {
+ parameter_dofs[local_coarse_dof](fine_dof) = 1.;
+ break;
+ };
+
+
+ // find out how many DoFs there are on the grids belonging to the
+ // components we want to match
+ unsigned int n_parameters_on_fine_grid=0;
+ if (true)
+ {
+ // have a flag for each dof on the fine grid and set it to true
+ // if this is an interesting dof. finally count how many true's
+ // there
+ std::vector<bool> dof_is_interesting (fine_grid.n_dofs(), false);
+ std::vector<types::global_dof_index> local_dof_indices (fine_fe.dofs_per_cell);
+
+ for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
+ cell=fine_grid.begin_active();
+ cell!=fine_grid.end(); ++cell)
+ {
+ cell->get_dof_indices (local_dof_indices);
+ for (unsigned int i=0; i<fine_fe.dofs_per_cell; ++i)
+ if (fine_fe.system_to_component_index(i).first == fine_component)
+ dof_is_interesting[local_dof_indices[i]] = true;
+ };
+
+ n_parameters_on_fine_grid = std::count (dof_is_interesting.begin(),
+ dof_is_interesting.end(),
+ true);
+ };
+
+
+ // set up the weights mapping
+ weights.clear ();
+ weights.resize (n_coarse_dofs);
+
+ weight_mapping.clear ();
+ weight_mapping.resize (n_fine_dofs, numbers::invalid_dof_index);
+
+ if (true)
+ {
+ std::vector<types::global_dof_index> local_dof_indices(fine_fe.dofs_per_cell);
+ unsigned int next_free_index=0;
+ for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
+ cell=fine_grid.begin_active();
+ cell != fine_grid.end(); ++cell)
+ {
+ cell->get_dof_indices (local_dof_indices);
+ for (unsigned int i=0; i<fine_fe.dofs_per_cell; ++i)
+ // if this DoF is a parameter dof and has not yet been
+ // numbered, then do so
+ if ((fine_fe.system_to_component_index(i).first == fine_component) &&
+ (weight_mapping[local_dof_indices[i]] == numbers::invalid_dof_index))
+ {
+ weight_mapping[local_dof_indices[i]] = next_free_index;
+ ++next_free_index;
+ };
+ };
+
+ Assert (next_free_index == n_parameters_on_fine_grid,
+ ExcInternalError());
+ };
+
+
+ // for each cell on the parameter grid: find out which degrees of
+ // freedom on the fine grid correspond in which way to the degrees
+ // of freedom on the parameter grid
+ //
+ // do this in a separate function to allow for multithreading
+ // there. see this function also if you want to read more
+ // information on the algorithm used.
+ compute_intergrid_weights_2 (coarse_grid, coarse_component,
+ coarse_to_fine_grid_map, parameter_dofs,
+ weight_mapping, weights);
+
+
+ // ok, now we have all weights for each dof on the fine grid. if in
+ // debug mode lets see if everything went smooth, i.e. each dof has
+ // sum of weights one
+ //
+ // in other words this means that if the sum of all shape functions
+ // on the parameter grid is one (which is always the case), then
+ // the representation on the state grid should be as well (division
+ // of unity)
+ //
+ // if the parameter grid has more than one component, then the
+ // respective dofs of the other components have sum of weights
+ // zero, of course. we do not explicitly ask which component a dof
+ // belongs to, but this at least tests some errors
+#ifdef DEBUG
+ for (unsigned int col=0; col<n_parameters_on_fine_grid; ++col)
+ {
+ double sum=0;
+ for (types::global_dof_index row=0; row<n_coarse_dofs; ++row)
+ if (weights[row].find(col) != weights[row].end())
+ sum += weights[row][col];
+ Assert ((std::fabs(sum-1) < 1.e-12) ||
+ ((coarse_fe.n_components()>1) && (sum==0)), ExcInternalError());
+ };
+#endif
+
+
+ return n_parameters_on_fine_grid;
+ }
+
+
+ }
+ }
+
+
+
+ template <int dim, int spacedim>
+ void
+ compute_intergrid_constraints (
+ const DoFHandler<dim,spacedim> &coarse_grid,
+ const unsigned int coarse_component,
+ const DoFHandler<dim,spacedim> &fine_grid,
+ const unsigned int fine_component,
+ const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+ ConstraintMatrix &constraints)
+ {
+ // store the weights with which a dof on the parameter grid contributes
+ // to a dof on the fine grid. see the long doc below for more info
+ //
+ // allocate as many rows as there are parameter dofs on the coarse grid
+ // and as many columns as there are parameter dofs on the fine grid.
+ //
+ // weight_mapping is used to map the global (fine grid) parameter dof
+ // indices to the columns
+ //
+ // in the original implementation, the weights array was actually of
+ // FullMatrix<double> type. this wasted huge amounts of memory, but was
+ // fast. nonetheless, since the memory consumption was quadratic in the
+ // number of degrees of freedom, this was not very practical, so we now
+ // use a vector of rows of the matrix, and in each row a vector of
+ // pairs (colnum,value). this seems like the best tradeoff between
+ // memory and speed, as it is now linear in memory and still fast
+ // enough.
+ //
+ // to save some memory and since the weights are usually (negative)
+ // powers of 2, we choose the value type of the matrix to be @p{float}
+ // rather than @p{double}.
+ std::vector<std::map<types::global_dof_index, float> > weights;
+
+ // this is this mapping. there is one entry for each dof on the fine
+ // grid; if it is a parameter dof, then its value is the column in
+ // weights for that parameter dof, if it is any other dof, then its
+ // value is -1, indicating an error
+ std::vector<types::global_dof_index> weight_mapping;
+
+ const unsigned int n_parameters_on_fine_grid
+ = internal::compute_intergrid_weights_1 (coarse_grid, coarse_component,
+ fine_grid, fine_component,
+ coarse_to_fine_grid_map,
+ weights, weight_mapping);
+
+ // global numbers of dofs
+ const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs(),
+ n_fine_dofs = fine_grid.n_dofs();
+
+
+ // get an array in which we store which dof on the coarse grid is a
+ // parameter and which is not
+ std::vector<bool> coarse_dof_is_parameter (coarse_grid.n_dofs());
+ if (true)
+ {
+ std::vector<bool> mask (coarse_grid.get_fe().n_components(),
+ false);
+ mask[coarse_component] = true;
+ extract_dofs (coarse_grid, ComponentMask(mask), coarse_dof_is_parameter);
+ }
+
+ // now we know that the weights in each row constitute a constraint.
+ // enter this into the constraints object
+ //
+ // first task: for each parameter dof on the parameter grid, find a
+ // representant on the fine, global grid. this is possible since we use
+ // conforming finite element. we take this representant to be the first
+ // element in this row with weight identical to one. the representant
+ // will become an unconstrained degree of freedom, while all others
+ // will be constrained to this dof (and possibly others)
+ std::vector<types::global_dof_index> representants(n_coarse_dofs, numbers::invalid_dof_index);
+ for (types::global_dof_index parameter_dof=0; parameter_dof<n_coarse_dofs;
+ ++parameter_dof)
+ if (coarse_dof_is_parameter[parameter_dof] == true)
+ {
+ // if this is the line of a parameter dof on the coarse grid,
+ // then it should have at least one dependent node on the fine
+ // grid
+ Assert (weights[parameter_dof].size() > 0, ExcInternalError());
+
+ // find the column where the representant is mentioned
+ std::map<types::global_dof_index,float>::const_iterator i = weights[parameter_dof].begin();
+ for (; i!=weights[parameter_dof].end(); ++i)
+ if (i->second == 1)
+ break;
+ Assert (i!=weights[parameter_dof].end(), ExcInternalError());
+ const types::global_dof_index column = i->first;
+
+ // now we know in which column of weights the representant is,
+ // but we don't know its global index. get it using the inverse
+ // operation of the weight_mapping
+ types::global_dof_index global_dof=0;
+ for (; global_dof<weight_mapping.size(); ++global_dof)
+ if (weight_mapping[global_dof] == static_cast<types::global_dof_index>(column))
+ break;
+ Assert (global_dof < weight_mapping.size(), ExcInternalError());
+
+ // now enter the representants global index into our list
+ representants[parameter_dof] = global_dof;
+ }
+ else
+ {
+ // consistency check: if this is no parameter dof on the coarse
+ // grid, then the respective row must be empty!
+ Assert (weights[parameter_dof].size() == 0, ExcInternalError());
+ };
+
+
+
+ // note for people that want to optimize this function: the largest
+ // part of the computing time is spent in the following, rather
+ // innocent block of code. basically, it must be the
+ // ConstraintMatrix::add_entry call which takes the bulk of the time,
+ // but it is not known to the author how to make it faster...
+ std::vector<std::pair<types::global_dof_index,double> > constraint_line;
+ for (types::global_dof_index global_dof=0; global_dof<n_fine_dofs; ++global_dof)
+ if (weight_mapping[global_dof] != numbers::invalid_dof_index)
+ // this global dof is a parameter dof, so it may carry a constraint
+ // note that for each global dof, the sum of weights shall be one,
+ // so we can find out whether this dof is constrained in the
+ // following way: if the only weight in this row is a one, and the
+ // representant for the parameter dof of the line in which this one
+ // is is the present dof, then we consider this dof to be
+ // unconstrained. otherwise, all other dofs are constrained
+ {
+ const types::global_dof_index col = weight_mapping[global_dof];
+ Assert (col < n_parameters_on_fine_grid, ExcInternalError());
+
+ types::global_dof_index first_used_row=0;
+
+ {
+ Assert (weights.size() > 0, ExcInternalError());
+ std::map<types::global_dof_index,float>::const_iterator
+ col_entry = weights[0].end();
+ for (; first_used_row<n_coarse_dofs; ++first_used_row)
+ {
+ col_entry = weights[first_used_row].find(col);
+ if (col_entry != weights[first_used_row].end())
+ break;
+ }
+
+ Assert (col_entry != weights[first_used_row].end(), ExcInternalError());
+
+ if ((col_entry->second == 1) &&
+ (representants[first_used_row] == global_dof))
+ // dof unconstrained or constrained to itself (in case this
+ // cell is mapped to itself, rather than to children of
+ // itself)
+ continue;
+ }
+
+
+ // otherwise enter all constraints
+ constraints.add_line (global_dof);
+
+ constraint_line.clear ();
+ for (types::global_dof_index row=first_used_row; row<n_coarse_dofs; ++row)
+ {
+ const std::map<types::global_dof_index,float>::const_iterator
+ j = weights[row].find(col);
+ if ((j != weights[row].end()) && (j->second != 0))
+ constraint_line.push_back (std::pair<types::global_dof_index,double>(representants[row],
+ j->second));
+ };
+
+ constraints.add_entries (global_dof, constraint_line);
+ };
+ }
+
+
+
+ template <int dim, int spacedim>
+ void
+ compute_intergrid_transfer_representation (
+ const DoFHandler<dim,spacedim> &coarse_grid,
+ const unsigned int coarse_component,
+ const DoFHandler<dim,spacedim> &fine_grid,
+ const unsigned int fine_component,
+ const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+ std::vector<std::map<types::global_dof_index, float> > &transfer_representation)
+ {
+ // store the weights with which a dof on the parameter grid contributes
+ // to a dof on the fine grid. see the long doc below for more info
+ //
+ // allocate as many rows as there are parameter dofs on the coarse grid
+ // and as many columns as there are parameter dofs on the fine grid.
+ //
+ // weight_mapping is used to map the global (fine grid) parameter dof
+ // indices to the columns
+ //
+ // in the original implementation, the weights array was actually of
+ // FullMatrix<double> type. this wasted huge amounts of memory, but was
+ // fast. nonetheless, since the memory consumption was quadratic in the
+ // number of degrees of freedom, this was not very practical, so we now
+ // use a vector of rows of the matrix, and in each row a vector of
+ // pairs (colnum,value). this seems like the best tradeoff between
+ // memory and speed, as it is now linear in memory and still fast
+ // enough.
+ //
+ // to save some memory and since the weights are usually (negative)
+ // powers of 2, we choose the value type of the matrix to be @p{float}
+ // rather than @p{double}.
+ std::vector<std::map<types::global_dof_index, float> > weights;
+
+ // this is this mapping. there is one entry for each dof on the fine
+ // grid; if it is a parameter dof, then its value is the column in
+ // weights for that parameter dof, if it is any other dof, then its
+ // value is -1, indicating an error
+ std::vector<types::global_dof_index> weight_mapping;
+
+ internal::compute_intergrid_weights_1 (coarse_grid, coarse_component,
+ fine_grid, fine_component,
+ coarse_to_fine_grid_map,
+ weights, weight_mapping);
+
+ // now compute the requested representation
+ const types::global_dof_index n_global_parm_dofs
+ = std::count_if (weight_mapping.begin(), weight_mapping.end(),
+ std::bind2nd (std::not_equal_to<types::global_dof_index> (), numbers::invalid_dof_index));
+
+ // first construct the inverse mapping of weight_mapping
+ std::vector<types::global_dof_index> inverse_weight_mapping (n_global_parm_dofs,
+ DoFHandler<dim,spacedim>::invalid_dof_index);
+ for (types::global_dof_index i=0; i<weight_mapping.size(); ++i)
+ {
+ const types::global_dof_index parameter_dof = weight_mapping[i];
+ // if this global dof is a parameter
+ if (parameter_dof != numbers::invalid_dof_index)
+ {
+ Assert (parameter_dof < n_global_parm_dofs, ExcInternalError());
+ Assert ((inverse_weight_mapping[parameter_dof] == DoFHandler<dim,spacedim>::invalid_dof_index),
+ ExcInternalError());
+
+ inverse_weight_mapping[parameter_dof] = i;
+ };
+ };
+
+ // next copy over weights array and replace respective numbers
+ const types::global_dof_index n_rows = weight_mapping.size();
+
+ transfer_representation.clear ();
+ transfer_representation.resize (n_rows);
+
+ const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs();
+ for (types::global_dof_index i=0; i<n_coarse_dofs; ++i)
+ {
+ std::map<types::global_dof_index, float>::const_iterator j = weights[i].begin();
+ for (; j!=weights[i].end(); ++j)
+ {
+ const types::global_dof_index p = inverse_weight_mapping[j->first];
+ Assert (p<n_rows, ExcInternalError());
+
+ transfer_representation[p][i] = j->second;
+ };
+ };
+ }
+
+
+
+ template <int dim, int spacedim, template <int,int> class DH>
+ void
+ make_zero_boundary_constraints (const DH<dim, spacedim> &dof,
+ const types::boundary_id boundary_indicator,
+ ConstraintMatrix &zero_boundary_constraints,
+ const ComponentMask &component_mask)
+ {
+ Assert (component_mask.represents_n_components(dof.get_fe().n_components()),
+ ExcMessage ("The number of components in the mask has to be either "
+ "zero or equal to the number of components in the finite "
+ "element."));
+
+ const unsigned int n_components = DoFTools::n_components (dof);
+
+ Assert (component_mask.n_selected_components(n_components) > 0,
+ ComponentMask::ExcNoComponentSelected());
+
+ // a field to store the indices
+ std::vector<types::global_dof_index> face_dofs;
+ face_dofs.reserve (max_dofs_per_face(dof));
+
+ typename DH<dim,spacedim>::active_cell_iterator
+ cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ if (!cell->is_artificial())
+ for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
+ ++face_no)
+ {
+ const FiniteElement<dim,spacedim> &fe = cell->get_fe();
+
+ const typename DH<dim,spacedim>::face_iterator face = cell->face(face_no);
+
+ // if face is on the boundary and satisfies the correct
+ // boundary id property
+ if (face->at_boundary ()
+ &&
+ ((boundary_indicator == numbers::invalid_boundary_id)
+ ||
+ (face->boundary_indicator() == boundary_indicator)))
+ {
+ // get indices and physical location on this face
+ face_dofs.resize (fe.dofs_per_face);
+ face->get_dof_indices (face_dofs, cell->active_fe_index());
+
+ // enter those dofs into the list that match the component
+ // signature.
+ for (unsigned int i=0; i<face_dofs.size(); ++i)
+ {
+ // Find out if a dof has a contribution in this
+ // component, and if so, add it to the list
+ const ComponentMask &nonzero_component_array
+ = cell->get_fe().get_nonzero_components (i);
+ bool nonzero = false;
+ for (unsigned int c=0; c<n_components; ++c)
+ if (nonzero_component_array[c] && component_mask[c])
+ {
+ nonzero = true;
+ break;
+ }
+
+ if (nonzero)
+ zero_boundary_constraints.add_line (face_dofs[i]);
+ }
+ }
+ }
+ }
+
+
+
+ template <int dim, int spacedim, template <int,int> class DH>
+ void
+ make_zero_boundary_constraints (const DH<dim, spacedim> &dof,
+ ConstraintMatrix &zero_boundary_constraints,
+ const ComponentMask &component_mask)
+ {
+ make_zero_boundary_constraints(dof, numbers::invalid_boundary_id,
+ zero_boundary_constraints, component_mask);
+ }
+
+
+} // end of namespace DoFTools
+
+
+
+// explicit instantiations
+
+#include "dof_tools_constraints.inst"
+
+
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+
+
+
+for (DH : DOFHANDLERS; deal_II_dimension : DIMENSIONS)
+{
+ template
+ void
+ DoFTools::make_hanging_node_constraints (const DH &dof_handler,
+ ConstraintMatrix &constraints);
+
+#if deal_II_dimension != 1
+ template
+ void
+ DoFTools::make_periodicity_constraints (const DH::face_iterator &,
+ const DH::face_iterator &,
+ dealii::ConstraintMatrix &,
+ const ComponentMask &,
+ bool, bool, bool);
+
+ template
+ void
+ DoFTools::make_periodicity_constraints(const DH &,
+ const types::boundary_id,
+ const types::boundary_id,
+ const int,
+ dealii::ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void
+ DoFTools::make_periodicity_constraints(const DH &,
+ const types::boundary_id,
+ const types::boundary_id,
+ const int,
+ dealii::Tensor<1,DH::space_dimension> &,
+ dealii::ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void
+ DoFTools::make_periodicity_constraints(const DH &,
+ const types::boundary_id,
+ const int,
+ dealii::ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void
+ DoFTools::make_periodicity_constraints(const DH &,
+ const types::boundary_id,
+ const int,
+ dealii::Tensor<1,DH::space_dimension> &,
+ dealii::ConstraintMatrix &,
+ const ComponentMask &);
+#endif
+}
+
+for (deal_II_dimension : DIMENSIONS)
+{
+#if deal_II_dimension != 1
+ template
+ void
+ DoFTools::make_hanging_node_constraints (const MGDoFHandler<deal_II_dimension> &dof_handler,
+ ConstraintMatrix &constraints);
+
+#endif
+
+#if deal_II_dimension < 3
+
+template
+void
+DoFTools::
+make_hanging_node_constraints (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_handler,
+ ConstraintMatrix &constraints);
+#endif
+
+#if deal_II_dimension == 3
+template
+void
+DoFTools::
+make_hanging_node_constraints (const DoFHandler<1,3> &dof_handler,
+ ConstraintMatrix &constraints);
+#endif
+
+template
+void
+DoFTools::make_zero_boundary_constraints
+(const DoFHandler<deal_II_dimension> &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+template
+void
+DoFTools::make_zero_boundary_constraints
+(const DoFHandler<deal_II_dimension> &,
+ const types::boundary_id ,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+template
+void
+DoFTools::make_zero_boundary_constraints
+(const hp::DoFHandler<deal_II_dimension> &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+template
+void
+DoFTools::make_zero_boundary_constraints
+(const hp::DoFHandler<deal_II_dimension> &,
+ const types::boundary_id ,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+template
+void
+DoFTools::compute_intergrid_constraints<deal_II_dimension> (
+ const DoFHandler<deal_II_dimension> &, const unsigned int,
+ const DoFHandler<deal_II_dimension> &, const unsigned int,
+ const InterGridMap<DoFHandler<deal_II_dimension> > &,
+ ConstraintMatrix&);
+
+template
+void
+DoFTools::compute_intergrid_transfer_representation<deal_II_dimension>
+(const DoFHandler<deal_II_dimension> &, const unsigned int,
+ const DoFHandler<deal_II_dimension> &, const unsigned int,
+ const InterGridMap<DoFHandler<deal_II_dimension> > &,
+ std::vector<std::map<types::global_dof_index, float> > &);
+
+}
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/multithread_info.h>
+#include <deal.II/base/thread_management.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/table.h>
+#include <deal.II/base/template_constraints.h>
+#include <deal.II/base/utilities.h>
+#include <deal.II/lac/sparsity_pattern.h>
+#include <deal.II/lac/compressed_sparsity_pattern.h>
+#include <deal.II/lac/compressed_set_sparsity_pattern.h>
+#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
+#include <deal.II/lac/trilinos_sparsity_pattern.h>
+#include <deal.II/lac/block_sparsity_pattern.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/intergrid_map.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/fe/fe.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/fe_tools.h>
+#include <deal.II/hp/fe_collection.h>
+#include <deal.II/hp/q_collection.h>
+#include <deal.II/hp/fe_values.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <deal.II/multigrid/mg_dof_handler.h>
+
+#include <algorithm>
+#include <numeric>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+namespace DoFTools
+{
+
+ template <class DH, class SparsityPattern>
+ void
+ make_sparsity_pattern (const DH &dof,
+ SparsityPattern &sparsity,
+ const ConstraintMatrix &constraints,
+ const bool keep_constrained_dofs,
+ const types::subdomain_id subdomain_id)
+ {
+ const types::global_dof_index n_dofs = dof.n_dofs();
+
+ Assert (sparsity.n_rows() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+ Assert (sparsity.n_cols() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
+
+ // If we have a distributed::Triangulation only allow locally_owned
+ // subdomain. Not setting a subdomain is also okay, because we skip
+ // ghost cells in the loop below.
+ Assert (
+ (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == dof.get_tria().locally_owned_subdomain()),
+ ExcMessage ("For parallel::distributed::Triangulation objects and "
+ "associated DoF handler objects, asking for any subdomain other "
+ "than the locally owned one does not make sense."));
+
+ std::vector<types::global_dof_index> dofs_on_this_cell;
+ dofs_on_this_cell.reserve (max_dofs_per_cell(dof));
+ typename DH::active_cell_iterator cell = dof.begin_active(),
+ endc = dof.end();
+
+ // In case we work with a distributed sparsity pattern of Trilinos
+ // type, we only have to do the work if the current cell is owned by
+ // the calling processor. Otherwise, just continue.
+ for (; cell!=endc; ++cell)
+ if (((subdomain_id == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == cell->subdomain_id()))
+ &&
+ cell->is_locally_owned())
+ {
+ const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
+ dofs_on_this_cell.resize (dofs_per_cell);
+ cell->get_dof_indices (dofs_on_this_cell);
+
+ // make sparsity pattern for this cell. if no constraints pattern
+ // was given, then the following call acts as if simply no
+ // constraints existed
+ constraints.add_entries_local_to_global (dofs_on_this_cell,
+ sparsity,
+ keep_constrained_dofs);
+ }
+ }
+
+
+
+ template <class DH, class SparsityPattern>
+ void
+ make_sparsity_pattern (const DH &dof,
+ const Table<2,Coupling> &couplings,
+ SparsityPattern &sparsity,
+ const ConstraintMatrix &constraints,
+ const bool keep_constrained_dofs,
+ const types::subdomain_id subdomain_id)
+ {
+ const types::global_dof_index n_dofs = dof.n_dofs();
+
+ Assert (sparsity.n_rows() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+ Assert (sparsity.n_cols() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
+ Assert (couplings.n_rows() == dof.get_fe().n_components(),
+ ExcDimensionMismatch(couplings.n_rows(), dof.get_fe().n_components()));
+ Assert (couplings.n_cols() == dof.get_fe().n_components(),
+ ExcDimensionMismatch(couplings.n_cols(), dof.get_fe().n_components()));
+
+ // If we have a distributed::Triangulation only allow locally_owned
+ // subdomain. Not setting a subdomain is also okay, because we skip
+ // ghost cells in the loop below.
+ Assert (
+ (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == dof.get_tria().locally_owned_subdomain()),
+ ExcMessage ("For parallel::distributed::Triangulation objects and "
+ "associated DoF handler objects, asking for any subdomain other "
+ "than the locally owned one does not make sense."));
+
+ const hp::FECollection<DH::dimension,DH::space_dimension> fe_collection (dof.get_fe());
+
+ // first, for each finite element, build a mask for each dof, not like
+ // the one given which represents components. make sure we do the right
+ // thing also with respect to non-primitive shape functions, which
+ // takes some additional thought
+ std::vector<Table<2,bool> > dof_mask(fe_collection.size());
+
+ // check whether the table of couplings contains only true arguments,
+ // i.e., we do not exclude any index. that is the easy case, since we
+ // don't have to set up the tables
+ bool need_dof_mask = false;
+ for (unsigned int i=0; i<couplings.n_rows(); ++i)
+ for (unsigned int j=0; j<couplings.n_cols(); ++j)
+ if (couplings(i,j) == none)
+ need_dof_mask = true;
+
+ if (need_dof_mask == true)
+ for (unsigned int f=0; f<fe_collection.size(); ++f)
+ {
+ const unsigned int dofs_per_cell = fe_collection[f].dofs_per_cell;
+
+ dof_mask[f].reinit (dofs_per_cell, dofs_per_cell);
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ if (fe_collection[f].is_primitive(i) &&
+ fe_collection[f].is_primitive(j))
+ dof_mask[f](i,j)
+ = (couplings(fe_collection[f].system_to_component_index(i).first,
+ fe_collection[f].system_to_component_index(j).first) != none);
+ else
+ {
+ const unsigned int first_nonzero_comp_i
+ = fe_collection[f].get_nonzero_components(i).first_selected_component();
+ const unsigned int first_nonzero_comp_j
+ = fe_collection[f].get_nonzero_components(j).first_selected_component();
+ Assert (first_nonzero_comp_i < fe_collection[f].n_components(),
+ ExcInternalError());
+ Assert (first_nonzero_comp_j < fe_collection[f].n_components(),
+ ExcInternalError());
+
+ dof_mask[f](i,j)
+ = (couplings(first_nonzero_comp_i,first_nonzero_comp_j) != none);
+ }
+ }
+
+
+ std::vector<types::global_dof_index> dofs_on_this_cell(fe_collection.max_dofs_per_cell());
+ typename DH::active_cell_iterator cell = dof.begin_active(),
+ endc = dof.end();
+
+ // In case we work with a distributed sparsity pattern of Trilinos
+ // type, we only have to do the work if the current cell is owned by
+ // the calling processor. Otherwise, just continue.
+ for (; cell!=endc; ++cell)
+ if (((subdomain_id == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == cell->subdomain_id()))
+ &&
+ cell->is_locally_owned())
+ {
+ const unsigned int fe_index = cell->active_fe_index();
+ const unsigned int dofs_per_cell =fe_collection[fe_index].dofs_per_cell;
+
+ dofs_on_this_cell.resize (dofs_per_cell);
+ cell->get_dof_indices (dofs_on_this_cell);
+
+
+ // make sparsity pattern for this cell. if no constraints pattern
+ // was given, then the following call acts as if simply no
+ // constraints existed
+ constraints.add_entries_local_to_global (dofs_on_this_cell,
+ sparsity,
+ keep_constrained_dofs,
+ dof_mask[fe_index]);
+ }
+ }
+
+
+
+ template <class DH, class SparsityPattern>
+ void
+ make_sparsity_pattern (
+ const DH &dof_row,
+ const DH &dof_col,
+ SparsityPattern &sparsity)
+ {
+ const types::global_dof_index n_dofs_row = dof_row.n_dofs();
+ const types::global_dof_index n_dofs_col = dof_col.n_dofs();
+
+ Assert (sparsity.n_rows() == n_dofs_row,
+ ExcDimensionMismatch (sparsity.n_rows(), n_dofs_row));
+ Assert (sparsity.n_cols() == n_dofs_col,
+ ExcDimensionMismatch (sparsity.n_cols(), n_dofs_col));
+
+//TODO: Looks like wasteful memory management here
+
+ const std::list<std::pair<typename DH::cell_iterator,
+ typename DH::cell_iterator> >
+ cell_list
+ = GridTools::get_finest_common_cells (dof_row, dof_col);
+
+
+ typename std::list<std::pair<typename DH::cell_iterator,
+ typename DH::cell_iterator> >::const_iterator
+ cell_iter = cell_list.begin();
+
+ for (; cell_iter!=cell_list.end(); ++cell_iter)
+ {
+ const typename DH::cell_iterator cell_row = cell_iter->first;
+ const typename DH::cell_iterator cell_col = cell_iter->second;
+
+ if (!cell_row->has_children() && !cell_col->has_children())
+ {
+ const unsigned int dofs_per_cell_row =
+ cell_row->get_fe().dofs_per_cell;
+ const unsigned int dofs_per_cell_col =
+ cell_col->get_fe().dofs_per_cell;
+ std::vector<types::global_dof_index>
+ local_dof_indices_row(dofs_per_cell_row);
+ std::vector<types::global_dof_index>
+ local_dof_indices_col(dofs_per_cell_col);
+ cell_row->get_dof_indices (local_dof_indices_row);
+ cell_col->get_dof_indices (local_dof_indices_col);
+ for (unsigned int i=0; i<dofs_per_cell_row; ++i)
+ sparsity.add_entries (local_dof_indices_row[i],
+ local_dof_indices_col.begin(),
+ local_dof_indices_col.end());
+ }
+ else if (cell_row->has_children())
+ {
+ const std::vector<typename DH::active_cell_iterator >
+ child_cells = GridTools::get_active_child_cells<DH> (cell_row);
+ for (unsigned int i=0; i<child_cells.size(); i++)
+ {
+ const typename DH::cell_iterator
+ cell_row_child = child_cells[i];
+ const unsigned int dofs_per_cell_row =
+ cell_row_child->get_fe().dofs_per_cell;
+ const unsigned int dofs_per_cell_col =
+ cell_col->get_fe().dofs_per_cell;
+ std::vector<types::global_dof_index>
+ local_dof_indices_row(dofs_per_cell_row);
+ std::vector<types::global_dof_index>
+ local_dof_indices_col(dofs_per_cell_col);
+ cell_row_child->get_dof_indices (local_dof_indices_row);
+ cell_col->get_dof_indices (local_dof_indices_col);
+ for (unsigned int i=0; i<dofs_per_cell_row; ++i)
+ sparsity.add_entries (local_dof_indices_row[i],
+ local_dof_indices_col.begin(),
+ local_dof_indices_col.end());
+ }
+ }
+ else
+ {
+ std::vector<typename DH::active_cell_iterator>
+ child_cells = GridTools::get_active_child_cells<DH> (cell_col);
+ for (unsigned int i=0; i<child_cells.size(); i++)
+ {
+ const typename DH::active_cell_iterator
+ cell_col_child = child_cells[i];
+ const unsigned int dofs_per_cell_row =
+ cell_row->get_fe().dofs_per_cell;
+ const unsigned int dofs_per_cell_col =
+ cell_col_child->get_fe().dofs_per_cell;
+ std::vector<types::global_dof_index>
+ local_dof_indices_row(dofs_per_cell_row);
+ std::vector<types::global_dof_index>
+ local_dof_indices_col(dofs_per_cell_col);
+ cell_row->get_dof_indices (local_dof_indices_row);
+ cell_col_child->get_dof_indices (local_dof_indices_col);
+ for (unsigned int i=0; i<dofs_per_cell_row; ++i)
+ sparsity.add_entries (local_dof_indices_row[i],
+ local_dof_indices_col.begin(),
+ local_dof_indices_col.end());
+ }
+ }
+ }
+ }
+
+
+
+ template <class DH, class SparsityPattern>
+ void
+ make_boundary_sparsity_pattern (
+ const DH &dof,
+ const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ SparsityPattern &sparsity)
+ {
+ if (DH::dimension == 1)
+ {
+ // there are only 2 boundary indicators in 1d, so it is no
+ // performance problem to call the other function
+ typename DH::FunctionMap boundary_indicators;
+ boundary_indicators[0] = 0;
+ boundary_indicators[1] = 0;
+ make_boundary_sparsity_pattern<DH, SparsityPattern> (dof,
+ boundary_indicators,
+ dof_to_boundary_mapping,
+ sparsity);
+ return;
+ }
+
+ const types::global_dof_index n_dofs = dof.n_dofs();
+
+ AssertDimension (dof_to_boundary_mapping.size(), n_dofs);
+ AssertDimension (sparsity.n_rows(), dof.n_boundary_dofs());
+ AssertDimension (sparsity.n_cols(), dof.n_boundary_dofs());
+#ifdef DEBUG
+ if (sparsity.n_rows() != 0)
+ {
+ types::global_dof_index max_element = 0;
+ for (std::vector<types::global_dof_index>::const_iterator i=dof_to_boundary_mapping.begin();
+ i!=dof_to_boundary_mapping.end(); ++i)
+ if ((*i != DH::invalid_dof_index) &&
+ (*i > max_element))
+ max_element = *i;
+ AssertDimension (max_element, sparsity.n_rows()-1);
+ };
+#endif
+
+ std::vector<types::global_dof_index> dofs_on_this_face;
+ dofs_on_this_face.reserve (max_dofs_per_face(dof));
+
+ // loop over all faces to check whether they are at a boundary. note
+ // that we need not take special care of single lines (using
+ // @p{cell->has_boundary_lines}), since we do not support boundaries of
+ // dimension dim-2, and so every boundary line is also part of a
+ // boundary face.
+ typename DH::active_cell_iterator cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
+ if (cell->at_boundary(f))
+ {
+ const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
+ dofs_on_this_face.resize (dofs_per_face);
+ cell->face(f)->get_dof_indices (dofs_on_this_face,
+ cell->active_fe_index());
+
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<dofs_per_face; ++i)
+ for (unsigned int j=0; j<dofs_per_face; ++j)
+ sparsity.add (dof_to_boundary_mapping[dofs_on_this_face[i]],
+ dof_to_boundary_mapping[dofs_on_this_face[j]]);
+ }
+ }
+
+
+
+ template <class DH, class SparsityPattern>
+ void make_boundary_sparsity_pattern (
+ const DH &dof,
+ const typename FunctionMap<DH::space_dimension>::type &boundary_indicators,
+ const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ SparsityPattern &sparsity)
+ {
+ if (DH::dimension == 1)
+ {
+ // first check left, then right boundary point
+ for (unsigned int direction=0; direction<2; ++direction)
+ {
+ // if this boundary is not requested, then go on with next one
+ if (boundary_indicators.find(direction) ==
+ boundary_indicators.end())
+ continue;
+
+ // find active cell at that boundary: first go to left/right,
+ // then to children
+ typename DH::level_cell_iterator cell = dof.begin(0);
+ while (!cell->at_boundary(direction))
+ cell = cell->neighbor(direction);
+ while (!cell->active())
+ cell = cell->child(direction);
+
+ const unsigned int dofs_per_vertex = cell->get_fe().dofs_per_vertex;
+ std::vector<types::global_dof_index> boundary_dof_boundary_indices (dofs_per_vertex);
+
+ // next get boundary mapped dof indices of boundary dofs
+ for (unsigned int i=0; i<dofs_per_vertex; ++i)
+ boundary_dof_boundary_indices[i]
+ = dof_to_boundary_mapping[cell->vertex_dof_index(direction,i)];
+
+ for (unsigned int i=0; i<dofs_per_vertex; ++i)
+ sparsity.add_entries (boundary_dof_boundary_indices[i],
+ boundary_dof_boundary_indices.begin(),
+ boundary_dof_boundary_indices.end());
+ };
+ return;
+ }
+
+ const types::global_dof_index n_dofs = dof.n_dofs();
+
+ AssertDimension (dof_to_boundary_mapping.size(), n_dofs);
+ Assert (boundary_indicators.find(numbers::internal_face_boundary_id) == boundary_indicators.end(),
+ typename DH::ExcInvalidBoundaryIndicator());
+ Assert (sparsity.n_rows() == dof.n_boundary_dofs (boundary_indicators),
+ ExcDimensionMismatch (sparsity.n_rows(), dof.n_boundary_dofs (boundary_indicators)));
+ Assert (sparsity.n_cols() == dof.n_boundary_dofs (boundary_indicators),
+ ExcDimensionMismatch (sparsity.n_cols(), dof.n_boundary_dofs (boundary_indicators)));
+#ifdef DEBUG
+ if (sparsity.n_rows() != 0)
+ {
+ types::global_dof_index max_element = 0;
+ for (std::vector<types::global_dof_index>::const_iterator i=dof_to_boundary_mapping.begin();
+ i!=dof_to_boundary_mapping.end(); ++i)
+ if ((*i != DH::invalid_dof_index) &&
+ (*i > max_element))
+ max_element = *i;
+ AssertDimension (max_element, sparsity.n_rows()-1);
+ };
+#endif
+
+ std::vector<types::global_dof_index> dofs_on_this_face;
+ dofs_on_this_face.reserve (max_dofs_per_face(dof));
+ typename DH::active_cell_iterator cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
+ if (boundary_indicators.find(cell->face(f)->boundary_indicator()) !=
+ boundary_indicators.end())
+ {
+ const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
+ dofs_on_this_face.resize (dofs_per_face);
+ cell->face(f)->get_dof_indices (dofs_on_this_face,
+ cell->active_fe_index());
+
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<dofs_per_face; ++i)
+ for (unsigned int j=0; j<dofs_per_face; ++j)
+ sparsity.add (dof_to_boundary_mapping[dofs_on_this_face[i]],
+ dof_to_boundary_mapping[dofs_on_this_face[j]]);
+ }
+ }
+
+
+
+ template <class DH, class SparsityPattern>
+ void
+ make_flux_sparsity_pattern (const DH &dof,
+ SparsityPattern &sparsity,
+ const ConstraintMatrix &constraints,
+ const bool keep_constrained_dofs,
+ const types::subdomain_id subdomain_id)
+
+ // TODO: QA: reduce the indentation level of this method..., Maier 2012
+
+ {
+ const types::global_dof_index n_dofs = dof.n_dofs();
+
+ AssertDimension (sparsity.n_rows(), n_dofs);
+ AssertDimension (sparsity.n_cols(), n_dofs);
+
+ // If we have a distributed::Triangulation only allow locally_owned
+ // subdomain. Not setting a subdomain is also okay, because we skip
+ // ghost cells in the loop below.
+ Assert (
+ (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == dof.get_tria().locally_owned_subdomain()),
+ ExcMessage ("For parallel::distributed::Triangulation objects and "
+ "associated DoF handler objects, asking for any subdomain other "
+ "than the locally owned one does not make sense."));
+
+ std::vector<types::global_dof_index> dofs_on_this_cell;
+ std::vector<types::global_dof_index> dofs_on_other_cell;
+ dofs_on_this_cell.reserve (max_dofs_per_cell(dof));
+ dofs_on_other_cell.reserve (max_dofs_per_cell(dof));
+ typename DH::active_cell_iterator cell = dof.begin_active(),
+ endc = dof.end();
+
+ // TODO: in an old implementation, we used user flags before to tag
+ // faces that were already touched. this way, we could reduce the work
+ // a little bit. now, we instead add only data from one side. this
+ // should be OK, but we need to actually verify it.
+
+ // In case we work with a distributed sparsity pattern of Trilinos
+ // type, we only have to do the work if the current cell is owned by
+ // the calling processor. Otherwise, just continue.
+ for (; cell!=endc; ++cell)
+ if (((subdomain_id == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id == cell->subdomain_id()))
+ &&
+ cell->is_locally_owned())
+ {
+ const unsigned int n_dofs_on_this_cell = cell->get_fe().dofs_per_cell;
+ dofs_on_this_cell.resize (n_dofs_on_this_cell);
+ cell->get_dof_indices (dofs_on_this_cell);
+
+ // make sparsity pattern for this cell. if no constraints pattern
+ // was given, then the following call acts as if simply no
+ // constraints existed
+ constraints.add_entries_local_to_global (dofs_on_this_cell,
+ sparsity,
+ keep_constrained_dofs);
+
+ for (unsigned int face = 0;
+ face < GeometryInfo<DH::dimension>::faces_per_cell;
+ ++face)
+ {
+ typename DH::face_iterator cell_face = cell->face(face);
+ if (! cell->at_boundary(face) )
+ {
+ typename DH::level_cell_iterator neighbor = cell->neighbor(face);
+
+ // in 1d, we do not need to worry whether the neighbor
+ // might have children and then loop over those children.
+ // rather, we may as well go straight to to cell behind
+ // this particular cell's most terminal child
+ if (DH::dimension==1)
+ while (neighbor->has_children())
+ neighbor = neighbor->child(face==0 ? 1 : 0);
+
+ if (neighbor->has_children())
+ {
+ for (unsigned int sub_nr = 0;
+ sub_nr != cell_face->number_of_children();
+ ++sub_nr)
+ {
+ const typename DH::level_cell_iterator
+ sub_neighbor
+ = cell->neighbor_child_on_subface (face, sub_nr);
+
+ const unsigned int n_dofs_on_neighbor
+ = sub_neighbor->get_fe().dofs_per_cell;
+ dofs_on_other_cell.resize (n_dofs_on_neighbor);
+ sub_neighbor->get_dof_indices (dofs_on_other_cell);
+
+ constraints.add_entries_local_to_global
+ (dofs_on_this_cell, dofs_on_other_cell,
+ sparsity, keep_constrained_dofs);
+ constraints.add_entries_local_to_global
+ (dofs_on_other_cell, dofs_on_this_cell,
+ sparsity, keep_constrained_dofs);
+ }
+ }
+ else
+ {
+ // Refinement edges are taken care of by coarser
+ // cells
+
+ // TODO: in the distributed case, we miss out the
+ // constraints when the neighbor cell is coarser, but
+ // only the current cell is owned locally!
+ if (cell->neighbor_is_coarser(face))
+ continue;
+
+ const unsigned int n_dofs_on_neighbor
+ = neighbor->get_fe().dofs_per_cell;
+ dofs_on_other_cell.resize (n_dofs_on_neighbor);
+
+ neighbor->get_dof_indices (dofs_on_other_cell);
+
+ constraints.add_entries_local_to_global
+ (dofs_on_this_cell, dofs_on_other_cell,
+ sparsity, keep_constrained_dofs);
+
+ // only need to add these in case the neighbor cell
+ // is not locally owned - otherwise, we touch each
+ // face twice and hence put the indices the other way
+ // around
+ if (!cell->neighbor(face)->active()
+ ||
+ (cell->neighbor(face)->subdomain_id() !=
+ cell->subdomain_id()))
+ constraints.add_entries_local_to_global
+ (dofs_on_other_cell, dofs_on_this_cell,
+ sparsity, keep_constrained_dofs);
+ }
+ }
+ }
+ }
+ }
+
+
+
+ template <class DH, class SparsityPattern>
+ void
+ make_flux_sparsity_pattern (const DH &dof,
+ SparsityPattern &sparsity)
+ {
+ ConstraintMatrix constraints;
+ make_flux_sparsity_pattern (dof, sparsity, constraints);
+ }
+
+ template <int dim, int spacedim>
+ Table<2,Coupling>
+ dof_couplings_from_component_couplings (const FiniteElement<dim,spacedim> &fe,
+ const Table<2,Coupling> &component_couplings)
+ {
+ Assert(component_couplings.n_rows() == fe.n_components(),
+ ExcDimensionMismatch(component_couplings.n_rows(),
+ fe.n_components()));
+ Assert(component_couplings.n_cols() == fe.n_components(),
+ ExcDimensionMismatch(component_couplings.n_cols(),
+ fe.n_components()));
+
+ const unsigned int n_dofs = fe.dofs_per_cell;
+
+ Table<2,Coupling> dof_couplings (n_dofs, n_dofs);
+
+ for (unsigned int i=0; i<n_dofs; ++i)
+ {
+ const unsigned int ii
+ = (fe.is_primitive(i) ?
+ fe.system_to_component_index(i).first
+ :
+ fe.get_nonzero_components(i).first_selected_component()
+ );
+ Assert (ii < fe.n_components(), ExcInternalError());
+
+ for (unsigned int j=0; j<n_dofs; ++j)
+ {
+ const unsigned int jj
+ = (fe.is_primitive(j) ?
+ fe.system_to_component_index(j).first
+ :
+ fe.get_nonzero_components(j).first_selected_component()
+ );
+ Assert (jj < fe.n_components(), ExcInternalError());
+
+ dof_couplings(i,j) = component_couplings(ii,jj);
+ }
+ }
+ return dof_couplings;
+ }
+
+
+
+ template <int dim, int spacedim>
+ std::vector<Table<2,Coupling> >
+ dof_couplings_from_component_couplings
+ (const hp::FECollection<dim,spacedim> &fe,
+ const Table<2,Coupling> &component_couplings)
+ {
+ std::vector<Table<2,Coupling> > return_value (fe.size());
+ for (unsigned int i=0; i<fe.size(); ++i)
+ return_value[i]
+ = dof_couplings_from_component_couplings(fe[i], component_couplings);
+
+ return return_value;
+ }
+
+
+
+ namespace internal
+ {
+ namespace
+ {
+
+ // implementation of the same function in namespace DoFTools for
+ // non-hp DoFHandlers
+ template <class DH, class SparsityPattern>
+ void
+ make_flux_sparsity_pattern (const DH &dof,
+ SparsityPattern &sparsity,
+ const Table<2,Coupling> &int_mask,
+ const Table<2,Coupling> &flux_mask)
+ {
+ const FiniteElement<DH::dimension,DH::space_dimension> &fe = dof.get_fe();
+
+ std::vector<types::global_dof_index> dofs_on_this_cell(fe.dofs_per_cell);
+ std::vector<types::global_dof_index> dofs_on_other_cell(fe.dofs_per_cell);
+
+ const Table<2,Coupling>
+ int_dof_mask = dof_couplings_from_component_couplings(fe, int_mask),
+ flux_dof_mask = dof_couplings_from_component_couplings(fe, flux_mask);
+
+ Table<2,bool> support_on_face(fe.dofs_per_cell,
+ GeometryInfo<DH::dimension>::faces_per_cell);
+ for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+ for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
+ support_on_face(i,f) = fe.has_support_on_face(i,f);
+
+ typename DH::active_cell_iterator cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ if (cell->is_locally_owned())
+ {
+ cell->get_dof_indices (dofs_on_this_cell);
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+ for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
+ if (int_dof_mask(i,j) != none)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+
+ // Loop over all interior neighbors
+ for (unsigned int face = 0;
+ face < GeometryInfo<DH::dimension>::faces_per_cell;
+ ++face)
+ {
+ const typename DH::face_iterator
+ cell_face = cell->face(face);
+ if (cell_face->user_flag_set ())
+ continue;
+
+ if (cell->at_boundary (face) )
+ {
+ for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+ {
+ const bool i_non_zero_i = support_on_face (i, face);
+ for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
+ {
+ const bool j_non_zero_i = support_on_face (j, face);
+
+ if ((flux_dof_mask(i,j) == always)
+ ||
+ (flux_dof_mask(i,j) == nonzero
+ &&
+ i_non_zero_i
+ &&
+ j_non_zero_i))
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ }
+ }
+ }
+ else
+ {
+ typename DH::level_cell_iterator
+ neighbor = cell->neighbor(face);
+ // Refinement edges are taken care of by coarser
+ // cells
+ if (cell->neighbor_is_coarser(face))
+ continue;
+
+ typename DH::face_iterator cell_face = cell->face(face);
+ const unsigned int
+ neighbor_face = cell->neighbor_of_neighbor(face);
+
+ if (cell_face->has_children())
+ {
+ for (unsigned int sub_nr = 0;
+ sub_nr != cell_face->n_children();
+ ++sub_nr)
+ {
+ const typename DH::level_cell_iterator
+ sub_neighbor
+ = cell->neighbor_child_on_subface (face, sub_nr);
+
+ sub_neighbor->get_dof_indices (dofs_on_other_cell);
+ for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+ {
+ const bool i_non_zero_i = support_on_face (i, face);
+ const bool i_non_zero_e = support_on_face (i, neighbor_face);
+ for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
+ {
+ const bool j_non_zero_i = support_on_face (j, face);
+ const bool j_non_zero_e = support_on_face (j, neighbor_face);
+
+ if (flux_dof_mask(i,j) == always)
+ {
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_other_cell[j]);
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_other_cell[j]);
+ }
+ else if (flux_dof_mask(i,j) == nonzero)
+ {
+ if (i_non_zero_i && j_non_zero_e)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_other_cell[j]);
+ if (i_non_zero_e && j_non_zero_i)
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ if (i_non_zero_i && j_non_zero_i)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ if (i_non_zero_e && j_non_zero_e)
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_other_cell[j]);
+ }
+
+ if (flux_dof_mask(j,i) == always)
+ {
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_other_cell[i]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_this_cell[i]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_other_cell[i]);
+ }
+ else if (flux_dof_mask(j,i) == nonzero)
+ {
+ if (j_non_zero_i && i_non_zero_e)
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_other_cell[i]);
+ if (j_non_zero_e && i_non_zero_i)
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ if (j_non_zero_i && i_non_zero_i)
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_this_cell[i]);
+ if (j_non_zero_e && i_non_zero_e)
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_other_cell[i]);
+ }
+ }
+ }
+ sub_neighbor->face(neighbor_face)->set_user_flag ();
+ }
+ }
+ else
+ {
+ neighbor->get_dof_indices (dofs_on_other_cell);
+ for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+ {
+ const bool i_non_zero_i = support_on_face (i, face);
+ const bool i_non_zero_e = support_on_face (i, neighbor_face);
+ for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
+ {
+ const bool j_non_zero_i = support_on_face (j, face);
+ const bool j_non_zero_e = support_on_face (j, neighbor_face);
+ if (flux_dof_mask(i,j) == always)
+ {
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_other_cell[j]);
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_other_cell[j]);
+ }
+ if (flux_dof_mask(i,j) == nonzero)
+ {
+ if (i_non_zero_i && j_non_zero_e)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_other_cell[j]);
+ if (i_non_zero_e && j_non_zero_i)
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ if (i_non_zero_i && j_non_zero_i)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ if (i_non_zero_e && j_non_zero_e)
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_other_cell[j]);
+ }
+
+ if (flux_dof_mask(j,i) == always)
+ {
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_other_cell[i]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_this_cell[i]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_other_cell[i]);
+ }
+ if (flux_dof_mask(j,i) == nonzero)
+ {
+ if (j_non_zero_i && i_non_zero_e)
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_other_cell[i]);
+ if (j_non_zero_e && i_non_zero_i)
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ if (j_non_zero_i && i_non_zero_i)
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_this_cell[i]);
+ if (j_non_zero_e && i_non_zero_e)
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_other_cell[i]);
+ }
+ }
+ }
+ neighbor->face(neighbor_face)->set_user_flag ();
+ }
+ }
+ }
+ }
+ }
+
+
+ // implementation of the same function in namespace DoFTools for
+ // non-hp DoFHandlers
+ template <int dim, int spacedim, class SparsityPattern>
+ void
+ make_flux_sparsity_pattern (const dealii::hp::DoFHandler<dim,spacedim> &dof,
+ SparsityPattern &sparsity,
+ const Table<2,Coupling> &int_mask,
+ const Table<2,Coupling> &flux_mask)
+ {
+ // while the implementation above is quite optimized and caches a
+ // lot of data (see e.g. the int/flux_dof_mask tables), this is no
+ // longer practical for the hp version since we would have to have
+ // it for all combinations of elements in the hp::FECollection.
+ // consequently, the implementation here is simpler and probably
+ // less efficient but at least readable...
+
+ const dealii::hp::FECollection<dim,spacedim> &fe = dof.get_fe();
+
+ std::vector<types::global_dof_index> dofs_on_this_cell(DoFTools::max_dofs_per_cell(dof));
+ std::vector<types::global_dof_index> dofs_on_other_cell(DoFTools::max_dofs_per_cell(dof));
+
+ const std::vector<Table<2,Coupling> >
+ int_dof_mask
+ = dof_couplings_from_component_couplings(fe, int_mask);
+
+ typename dealii::hp::DoFHandler<dim,spacedim>::active_cell_iterator
+ cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ {
+ dofs_on_this_cell.resize (cell->get_fe().dofs_per_cell);
+ cell->get_dof_indices (dofs_on_this_cell);
+
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+ for (unsigned int j=0; j<cell->get_fe().dofs_per_cell; ++j)
+ if (int_dof_mask[cell->active_fe_index()](i,j) != none)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+
+ // Loop over all interior neighbors
+ for (unsigned int face = 0;
+ face < GeometryInfo<dim>::faces_per_cell;
+ ++face)
+ {
+ const typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
+ cell_face = cell->face(face);
+ if (cell_face->user_flag_set ())
+ continue;
+
+ if (cell->at_boundary (face) )
+ {
+ for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+ for (unsigned int j=0; j<cell->get_fe().dofs_per_cell; ++j)
+ if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
+ cell->get_fe().system_to_component_index(j).first)
+ == always)
+ ||
+ (flux_mask(cell->get_fe().system_to_component_index(i).first,
+ cell->get_fe().system_to_component_index(j).first)
+ == nonzero))
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ }
+ else
+ {
+ typename dealii::hp::DoFHandler<dim,spacedim>::level_cell_iterator
+ neighbor = cell->neighbor(face);
+
+ // Refinement edges are taken care of by coarser cells
+ if (cell->neighbor_is_coarser(face))
+ continue;
+
+ typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
+ cell_face = cell->face(face);
+ const unsigned int
+ neighbor_face = cell->neighbor_of_neighbor(face);
+
+ if (cell_face->has_children())
+ {
+ for (unsigned int sub_nr = 0;
+ sub_nr != cell_face->n_children();
+ ++sub_nr)
+ {
+ const typename dealii::hp::DoFHandler<dim,spacedim>::level_cell_iterator
+ sub_neighbor
+ = cell->neighbor_child_on_subface (face, sub_nr);
+
+ dofs_on_other_cell.resize (sub_neighbor->get_fe().dofs_per_cell);
+ sub_neighbor->get_dof_indices (dofs_on_other_cell);
+ for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<sub_neighbor->get_fe().dofs_per_cell;
+ ++j)
+ {
+ if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
+ sub_neighbor->get_fe().system_to_component_index(j).first)
+ == always)
+ ||
+ (flux_mask(cell->get_fe().system_to_component_index(i).first,
+ sub_neighbor->get_fe().system_to_component_index(j).first)
+ == nonzero))
+ {
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_other_cell[j]);
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_other_cell[j]);
+ }
+
+ if ((flux_mask(sub_neighbor->get_fe().system_to_component_index(j).first,
+ cell->get_fe().system_to_component_index(i).first)
+ == always)
+ ||
+ (flux_mask(sub_neighbor->get_fe().system_to_component_index(j).first,
+ cell->get_fe().system_to_component_index(i).first)
+ == nonzero))
+ {
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_other_cell[i]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_this_cell[i]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_other_cell[i]);
+ }
+ }
+ }
+ sub_neighbor->face(neighbor_face)->set_user_flag ();
+ }
+ }
+ else
+ {
+ dofs_on_other_cell.resize (neighbor->get_fe().dofs_per_cell);
+ neighbor->get_dof_indices (dofs_on_other_cell);
+ for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<neighbor->get_fe().dofs_per_cell; ++j)
+ {
+ if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
+ neighbor->get_fe().system_to_component_index(j).first)
+ == always)
+ ||
+ (flux_mask(cell->get_fe().system_to_component_index(i).first,
+ neighbor->get_fe().system_to_component_index(j).first)
+ == nonzero))
+ {
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_other_cell[j]);
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_other_cell[j]);
+ }
+
+ if ((flux_mask(neighbor->get_fe().system_to_component_index(j).first,
+ cell->get_fe().system_to_component_index(i).first)
+ == always)
+ ||
+ (flux_mask(neighbor->get_fe().system_to_component_index(j).first,
+ cell->get_fe().system_to_component_index(i).first)
+ == nonzero))
+ {
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_other_cell[i]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_this_cell[i]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_other_cell[i]);
+ }
+ }
+ }
+ neighbor->face(neighbor_face)->set_user_flag ();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+
+
+
+ template <class DH, class SparsityPattern>
+ void
+ make_flux_sparsity_pattern (const DH &dof,
+ SparsityPattern &sparsity,
+ const Table<2,Coupling> &int_mask,
+ const Table<2,Coupling> &flux_mask)
+ {
+ // do the error checking and frame code here, and then pass on to more
+ // specialized functions in the internal namespace
+ const types::global_dof_index n_dofs = dof.n_dofs();
+ const unsigned int n_comp = dof.get_fe().n_components();
+
+ Assert (sparsity.n_rows() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+ Assert (sparsity.n_cols() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
+ Assert (int_mask.n_rows() == n_comp,
+ ExcDimensionMismatch (int_mask.n_rows(), n_comp));
+ Assert (int_mask.n_cols() == n_comp,
+ ExcDimensionMismatch (int_mask.n_cols(), n_comp));
+ Assert (flux_mask.n_rows() == n_comp,
+ ExcDimensionMismatch (flux_mask.n_rows(), n_comp));
+ Assert (flux_mask.n_cols() == n_comp,
+ ExcDimensionMismatch (flux_mask.n_cols(), n_comp));
+
+ // Clear user flags because we will need them. But first we save them
+ // and make sure that we restore them later such that at the end of
+ // this function the Triangulation will be in the same state as it was
+ // at the beginning of this function.
+ std::vector<bool> user_flags;
+ dof.get_tria().save_user_flags(user_flags);
+ const_cast<Triangulation<DH::dimension,DH::space_dimension> &>(dof.get_tria()).clear_user_flags ();
+
+ internal::make_flux_sparsity_pattern (dof, sparsity,
+ int_mask, flux_mask);
+
+ // finally restore the user flags
+ const_cast<Triangulation<DH::dimension,DH::space_dimension> &>(dof.get_tria()).load_user_flags(user_flags);
+ }
+
+
+} // end of namespace DoFTools
+
+
+// --------------------------------------------------- explicit instantiations
+
+#include "dof_tools_sparsity.inst"
+
+
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+
+
+for (SP : SPARSITY_PATTERNS; deal_II_dimension : DIMENSIONS)
+ {
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+ (const DoFHandler<deal_II_dimension,deal_II_dimension> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<MGDoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+ (const MGDoFHandler<deal_II_dimension,deal_II_dimension> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+ (const DoFHandler<deal_II_dimension,deal_II_dimension>&,
+ const Table<2,Coupling>&,
+ SP &,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_dimension>&,
+ const Table<2,Coupling>&,
+ SP &,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<MGDoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+ (const MGDoFHandler<deal_II_dimension,deal_II_dimension>&,
+ const Table<2,Coupling>&,
+ SP &,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+ (const DoFHandler<deal_II_dimension,deal_II_dimension> &dof_row,
+ const DoFHandler<deal_II_dimension,deal_II_dimension> &dof_col,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof_row,
+ const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof_col,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+ (const DoFHandler<deal_II_dimension>& dof,
+ const std::vector<types::global_dof_index> &,
+ SP &);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+ (const hp::DoFHandler<deal_II_dimension>& dof,
+ const std::vector<types::global_dof_index> &,
+ SP &);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+ (const DoFHandler<deal_II_dimension>& dof,
+ const FunctionMap<deal_II_dimension>::type &boundary_indicators,
+ const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+ (const hp::DoFHandler<deal_II_dimension>& dof,
+ const FunctionMap<deal_II_dimension>::type &boundary_indicators,
+ const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ SP &sparsity);
+
+#if deal_II_dimension < 3
+ template void
+ DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+ const FunctionMap<deal_II_dimension+1>::type &boundary_indicators,
+ const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ SP &sparsity);
+ #endif
+
+ template void
+ DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+ (const DoFHandler<deal_II_dimension> &dof,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+ (const hp::DoFHandler<deal_II_dimension> &dof,
+ SP &sparsity);
+
+#if deal_II_dimension > 1
+
+ template void
+ DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+ (const DoFHandler<deal_II_dimension> &dof,
+ SP &,
+ const Table<2,Coupling>&,
+ const Table<2,Coupling>&);
+
+ template void
+ DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+ (const DoFHandler<deal_II_dimension> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &constraints,
+ const bool, const unsigned int);
+
+ template void
+ DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+ (const hp::DoFHandler<deal_II_dimension> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &constraints,
+ const bool, const unsigned int);
+
+ template void
+ DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+ (const hp::DoFHandler<deal_II_dimension> &dof,
+ SP &,
+ const Table<2,Coupling>&,
+ const Table<2,Coupling>&);
+#endif
+
+#if deal_II_dimension < 3
+
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+ (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+ (const DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
+ const Table<2,Coupling>&,
+ SP &,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
+ const Table<2,Coupling>&,
+ SP &,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+ (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_row,
+ const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_col,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_row,
+ const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_col,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+ (const DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+ const std::vector<types::global_dof_index> &,
+ SP &);
+
+ //template void
+ //DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+ //(const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+ // const std::vector<types::global_dof_index> &,
+ // SP &);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+ (const DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+ const FunctionMap<deal_II_dimension+1>::type &boundary_indicators,
+ const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ SP &sparsity);
+
+ //template void
+ //DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+ //(const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+ // const FunctionMap<deal_II_dimension+1>::type &boundary_indicators,
+ // const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ // SP &sparsity);
+
+#endif
+
+
+#if deal_II_dimension == 3
+
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
+ (const DoFHandler<1,3> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
+ (const hp::DoFHandler<1,3> &dof,
+ SP &sparsity,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
+ (const DoFHandler<1,3>&,
+ const Table<2,Coupling>&,
+ SP &,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
+ (const hp::DoFHandler<1,3>&,
+ const Table<2,Coupling>&,
+ SP &,
+ const ConstraintMatrix &,
+ const bool,
+ const unsigned int);
+
+ template void
+ DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
+ (const DoFHandler<1,3> &dof_row,
+ const DoFHandler<1,3> &dof_col,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
+ (const hp::DoFHandler<1,3> &dof_row,
+ const hp::DoFHandler<1,3> &dof_col,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<DoFHandler<1,3>,SP>
+ (const DoFHandler<1,3>& dof,
+ const std::vector<types::global_dof_index> &,
+ SP &);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<1,3>,SP>
+ (const hp::DoFHandler<1,3>& dof,
+ const std::vector<types::global_dof_index> &,
+ SP &);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<DoFHandler<1,3>,SP>
+ (const DoFHandler<1,3>& dof,
+ const FunctionMap<3>::type &boundary_indicators,
+ const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ SP &sparsity);
+
+ template void
+ DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<1,3>,SP>
+ (const hp::DoFHandler<1,3>& dof,
+ const FunctionMap<3>::type &boundary_indicators,
+ const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+ SP &sparsity);
+
+#endif
+
+ }
+
+
+for (deal_II_dimension : DIMENSIONS)
+{
+ template
+ Table<2,DoFTools::Coupling>
+ DoFTools::dof_couplings_from_component_couplings
+ (const FiniteElement<deal_II_dimension> &fe,
+ const Table<2,DoFTools::Coupling> &component_couplings);
+}
fe_raviart_thomas_nodal.cc
fe_system.cc
fe_tools.cc
+ fe_tools_interpolate.cc
fe_values.cc
fe_values_inst2.cc
mapping_c1.cc
fe_raviart_thomas_nodal.inst.in
fe_system.inst.in
fe_tools.inst.in
+ fe_tools_interpolate.inst.in
fe_values.decl.1.inst.in
fe_values.decl.2.inst.in
fe_values.impl.1.inst.in
system_to_component_table.resize(this->dofs_per_cell);
face_system_to_component_table.resize(this->dofs_per_face);
for (unsigned int j=0 ; j<this->dofs_per_cell ; ++j)
- {
- system_to_component_table[j] = std::pair<unsigned,unsigned>(0,j);
- system_to_base_table[j] = std::make_pair(std::make_pair(0U,0U),j);
- }
+ system_to_component_table[j] = std::pair<unsigned,unsigned>(0,j);
for (unsigned int j=0 ; j<this->dofs_per_face ; ++j)
- {
- face_system_to_component_table[j] = std::pair<unsigned,unsigned>(0,j);
- face_system_to_base_table[j] = std::make_pair(std::make_pair(0U,0U),j);
- }
+ face_system_to_component_table[j] = std::pair<unsigned,unsigned>(0,j);
}
+
+ for (unsigned int j=0 ; j<this->dofs_per_cell ; ++j)
+ system_to_base_table[j] = std::make_pair(std::make_pair(0U,0U),j);
+ for (unsigned int j=0 ; j<this->dofs_per_face ; ++j)
+ face_system_to_base_table[j] = std::make_pair(std::make_pair(0U,0U),j);
+
// Fill with default value; may be changed by constructor of derived class.
base_to_block_indices.reinit(1,1);
get_interpolation_matrix (const FiniteElement<dim,spacedim> &x_source_fe,
FullMatrix<double> &interpolation_matrix) const
{
- // this is only implemented, if the source FE is also a Q element
- AssertThrow ((dynamic_cast<const FE_Q_Base<POLY,dim,spacedim> *>(&x_source_fe) != 0),
- (typename FiniteElement<dim,spacedim>::ExcInterpolationNotImplemented()));
+ // go through the list of elements we can interpolate from
+ if (const FE_Q_Base<POLY,dim,spacedim> *source_fe
+ = dynamic_cast<const FE_Q_Base<POLY,dim,spacedim>*>(&x_source_fe))
+ {
+ // ok, source is a Q element, so we will be able to do the work
+ Assert (interpolation_matrix.m() == this->dofs_per_cell,
+ ExcDimensionMismatch (interpolation_matrix.m(),
+ this->dofs_per_cell));
+ Assert (interpolation_matrix.n() == x_source_fe.dofs_per_cell,
+ ExcDimensionMismatch (interpolation_matrix.m(),
+ x_source_fe.dofs_per_cell));
+
+ // only evaluate Q dofs
+ const unsigned int q_dofs_per_cell = Utilities::fixed_power<dim>(this->degree+1);
+ const unsigned int source_q_dofs_per_cell = Utilities::fixed_power<dim>(source_fe->degree+1);
- Assert (interpolation_matrix.m() == this->dofs_per_cell,
- ExcDimensionMismatch (interpolation_matrix.m(),
- this->dofs_per_cell));
- Assert (interpolation_matrix.n() == x_source_fe.dofs_per_cell,
- ExcDimensionMismatch (interpolation_matrix.m(),
- x_source_fe.dofs_per_cell));
+ // evaluation is simply done by evaluating the other FE's basis functions on
+ // the unit support points (FE_Q has the property that the cell
+ // interpolation matrix is a unit matrix, so no need to evaluate it and
+ // invert it)
+ for (unsigned int j=0; j<q_dofs_per_cell; ++j)
+ {
+ // read in a point on this cell and evaluate the shape functions there
+ const Point<dim> p = this->unit_support_points[j];
- // ok, source is a Q element, so we will be able to do the work
- const FE_Q_Base<POLY,dim,spacedim> &source_fe
- = dynamic_cast<const FE_Q_Base<POLY,dim,spacedim>&>(x_source_fe);
+ // FE_Q element evaluates to 1 in unit support point and to zero in all
+ // other points by construction
+ Assert(std::abs(this->poly_space.compute_value (j, p)-1.)<1e-13,
+ ExcInternalError());
- // only evaluate Q dofs
- const unsigned int q_dofs_per_cell = Utilities::fixed_power<dim>(this->degree+1);
- const unsigned int source_q_dofs_per_cell = Utilities::fixed_power<dim>(source_fe.degree+1);
+ for (unsigned int i=0; i<source_q_dofs_per_cell; ++i)
+ interpolation_matrix(j,i) = source_fe->poly_space.compute_value (i, p);
+ }
- // evaluation is simply done by evaluating the other FE's basis functions on
- // the unit support points (FE_Q has the property that the cell
- // interpolation matrix is a unit matrix, so no need to evaluate it and
- // invert it)
- for (unsigned int j=0; j<q_dofs_per_cell; ++j)
- {
- // read in a point on this cell and evaluate the shape functions there
- const Point<dim> p = this->unit_support_points[j];
+ // for FE_Q_DG0, add one last row of identity
+ if (q_dofs_per_cell < this->dofs_per_cell)
+ {
+ AssertDimension(source_q_dofs_per_cell+1, source_fe->dofs_per_cell);
+ for (unsigned int i=0; i<source_q_dofs_per_cell; ++i)
+ interpolation_matrix(q_dofs_per_cell, i) = 0.;
+ for (unsigned int j=0; j<q_dofs_per_cell; ++j)
+ interpolation_matrix(j, source_q_dofs_per_cell) = 0.;
+ interpolation_matrix(q_dofs_per_cell, source_q_dofs_per_cell) = 1.;
+ }
- // FE_Q element evaluates to 1 in unit support point and to zero in all
- // other points by construction
- Assert(std::abs(this->poly_space.compute_value (j, p)-1.)<1e-13,
- ExcInternalError());
+ // cut off very small values
+ const double eps = 2e-13*this->degree*dim;
+ for (unsigned int i=0; i<this->dofs_per_cell; ++i)
+ for (unsigned int j=0; j<source_fe->dofs_per_cell; ++j)
+ if (std::fabs(interpolation_matrix(i,j)) < eps)
+ interpolation_matrix(i,j) = 0.;
- for (unsigned int i=0; i<source_q_dofs_per_cell; ++i)
- interpolation_matrix(j,i) = source_fe.poly_space.compute_value (i, p);
- }
+ // 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 i=0; i<this->dofs_per_cell; ++i)
+ {
+ double sum = 0.;
+ for (unsigned int j=0; j<source_fe->dofs_per_cell; ++j)
+ sum += interpolation_matrix(i,j);
- // for FE_Q_DG0, add one last row of identity
- if (q_dofs_per_cell < this->dofs_per_cell)
- {
- AssertDimension(source_q_dofs_per_cell+1, source_fe.dofs_per_cell);
- for (unsigned int i=0; i<source_q_dofs_per_cell; ++i)
- interpolation_matrix(q_dofs_per_cell, i) = 0.;
- for (unsigned int j=0; j<q_dofs_per_cell; ++j)
- interpolation_matrix(j, source_q_dofs_per_cell) = 0.;
- interpolation_matrix(q_dofs_per_cell, source_q_dofs_per_cell) = 1.;
+ Assert (std::fabs(sum-1) < eps, ExcInternalError());
+ }
}
-
- // cut off very small values
- const double eps = 2e-13*this->degree*dim;
- for (unsigned int i=0; i<this->dofs_per_cell; ++i)
- for (unsigned int j=0; j<source_fe.dofs_per_cell; ++j)
- if (std::fabs(interpolation_matrix(i,j)) < eps)
- interpolation_matrix(i,j) = 0.;
-
- // 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 i=0; i<this->dofs_per_cell; ++i)
+ else if (dynamic_cast<const FE_Nothing<dim>*>(&x_source_fe))
{
- double sum = 0.;
- for (unsigned int j=0; j<source_fe.dofs_per_cell; ++j)
- sum += interpolation_matrix(i,j);
+ // the element we want to interpolate from is an FE_Nothing. this
+ // element represents a function that is constant zero and has no
+ // degrees of freedom, so the interpolation is simply a multiplication
+ // with a n_dofs x 0 matrix. there is nothing to do here
+
+ // we would like to verify that the number of rows and columns of
+ // the matrix equals this->dofs_per_cell and zero. unfortunately,
+ // whenever we do FullMatrix::reinit(m,0), it sets both rows and
+ // columns to zero, instead of m and zero. thus, only test the
+ // number of columns
+ Assert (interpolation_matrix.n() == x_source_fe.dofs_per_cell,
+ ExcDimensionMismatch (interpolation_matrix.m(),
+ x_source_fe.dofs_per_cell));
- Assert (std::fabs(sum-1) < eps, ExcInternalError());
}
+ else
+ AssertThrow (false,
+ (typename FiniteElement<dim,spacedim>::ExcInterpolationNotImplemented()));
+
}
#include <deal.II/base/utilities.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/householder.h>
-#include <deal.II/lac/vector.h>
-#include <deal.II/lac/block_vector.h>
-#include <deal.II/lac/parallel_vector.h>
-#include <deal.II/lac/parallel_block_vector.h>
-#include <deal.II/lac/petsc_parallel_vector.h>
-#include <deal.II/lac/petsc_block_vector.h>
-#include <deal.II/lac/petsc_parallel_block_vector.h>
-#include <deal.II/lac/trilinos_vector.h>
-#include <deal.II/lac/trilinos_block_vector.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_iterator.h>
start_indices[i] = k;
k += block_data[i];
}
-
-//TODO:[GK] This does not work for a single RT
+
for (unsigned int i=0; i<element.dofs_per_cell; ++i)
{
std::pair<unsigned int, types::global_dof_index>
}
- template <int dim, int spacedim,
- template <int, int> class DH1,
- template <int, int> class DH2,
- class InVector, class OutVector>
- void
- interpolate(const DH1<dim, spacedim> &dof1,
- const InVector &u1,
- const DH2<dim, spacedim> &dof2,
- OutVector &u2)
- {
- ConstraintMatrix dummy;
- dummy.close();
- interpolate(dof1, u1, dof2, dummy, u2);
- }
-
-
-
- template <int dim, int spacedim,
- template <int, int> class DH1,
- template <int, int> class DH2,
- class InVector, class OutVector>
- void
- interpolate (const DH1<dim, spacedim> &dof1,
- const InVector &u1,
- const DH2<dim, spacedim> &dof2,
- const ConstraintMatrix &constraints,
- OutVector &u2)
- {
- Assert(&dof1.get_tria()==&dof2.get_tria(), ExcTriangulationMismatch());
-
- Assert(u1.size()==dof1.n_dofs(),
- ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
- Assert(u2.size()==dof2.n_dofs(),
- ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
-
-#ifdef DEAL_II_WITH_PETSC
- if (dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1) != 0)
- if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
- {
- // if u1 is a parallel distributed
- // PETSc vector, we check the local
- // size of u1 for safety
- Assert(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size() == dof1.locally_owned_dofs().n_elements(),
- ExcDimensionMismatch(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size(), dof1.locally_owned_dofs().n_elements()));
- };
-
- if (dynamic_cast<PETScWrappers::MPI::Vector *>(&u2) != 0)
- if (dynamic_cast<const DoFHandler<dim>*>(&dof2) != 0)
- {
- Assert(dynamic_cast<PETScWrappers::MPI::Vector *>(&u2)->local_size() == dof2.locally_owned_dofs().n_elements(),
- ExcDimensionMismatch(dynamic_cast<PETScWrappers::MPI::Vector *>(&u2)->local_size(), dof2.locally_owned_dofs().n_elements()));
- };
-#endif
- // allocate vectors at maximal
- // size. will be reinited in inner
- // cell, but Vector makes sure that
- // this does not lead to
- // reallocation of memory
- Vector<typename OutVector::value_type> u1_local(DoFTools::max_dofs_per_cell(dof1));
- Vector<typename OutVector::value_type> u2_local(DoFTools::max_dofs_per_cell(dof2));
-
- // have a map for interpolation
- // matrices. shared_ptr make sure
- // that memory is released again
- std::map<const FiniteElement<dim,spacedim> *,
- std::map<const FiniteElement<dim,spacedim> *,
- std_cxx1x::shared_ptr<FullMatrix<double> > > >
- interpolation_matrices;
-
- typename DH1<dim,spacedim>::active_cell_iterator cell1 = dof1.begin_active(),
- endc1 = dof1.end();
- typename DH2<dim,spacedim>::active_cell_iterator cell2 = dof2.begin_active(),
- endc2 = dof2.end();
-
- std::vector<types::global_dof_index> dofs;
- dofs.reserve (DoFTools::max_dofs_per_cell (dof2));
-
- u2 = 0;
- OutVector touch_count(u2);
- touch_count = 0;
-
- // for distributed triangulations,
- // we can only interpolate u1 on
- // a cell, which this processor owns,
- // so we have to know the subdomain_id
- const types::subdomain_id subdomain_id =
- dof1.get_tria().locally_owned_subdomain();
-
- for (; cell1!=endc1; ++cell1, ++cell2)
- if ((cell1->subdomain_id() == subdomain_id)
- ||
- (subdomain_id == numbers::invalid_subdomain_id))
- {
- Assert(cell1->get_fe().n_components() == cell2->get_fe().n_components(),
- ExcDimensionMismatch (cell1->get_fe().n_components(),
- cell2->get_fe().n_components()));
-
- // for continuous elements on
- // grids with hanging nodes we
- // need hanging node
- // constraints. Consequentely,
- // if there are no constraints
- // then hanging nodes are not
- // allowed.
- const bool hanging_nodes_not_allowed
- = ((cell2->get_fe().dofs_per_vertex != 0) &&
- (constraints.n_constraints() == 0));
-
- if (hanging_nodes_not_allowed)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- Assert (cell1->at_boundary(face) ||
- cell1->neighbor(face)->level() == cell1->level(),
- ExcHangingNodesNotAllowed(0));
-
-
- const unsigned int dofs_per_cell1 = cell1->get_fe().dofs_per_cell;
- const unsigned int dofs_per_cell2 = cell2->get_fe().dofs_per_cell;
- u1_local.reinit (dofs_per_cell1);
- u2_local.reinit (dofs_per_cell2);
-
- // check if interpolation
- // matrix for this particular
- // pair of elements is already
- // there
- if (interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()].get() == 0)
- {
- std_cxx1x::shared_ptr<FullMatrix<double> >
- interpolation_matrix (new FullMatrix<double> (dofs_per_cell2,
- dofs_per_cell1));
- interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()]
- = interpolation_matrix;
-
- get_interpolation_matrix(cell1->get_fe(),
- cell2->get_fe(),
- *interpolation_matrix);
- }
-
- cell1->get_dof_values(u1, u1_local);
- interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()]
- ->vmult(u2_local, u1_local);
-
- dofs.resize (dofs_per_cell2);
- cell2->get_dof_indices(dofs);
-
- for (unsigned int i=0; i<dofs_per_cell2; ++i)
- {
- u2(dofs[i])+=u2_local(i);
- touch_count(dofs[i]) += 1;
- }
- }
- // cell1 is at the end, so should
- // be cell2
- Assert (cell2 == endc2, ExcInternalError());
-
- u2.compress(VectorOperation::add);
- touch_count.compress(VectorOperation::add);
-
- // if we work on parallel distributed
- // vectors, we have to ensure, that we only
- // work on dofs this processor owns.
- IndexSet locally_owned_dofs = dof2.locally_owned_dofs();
-
- // when a discontinuous element is
- // interpolated to a continuous
- // one, we take the mean values.
- // for parallel vectors check,
- // if this component is owned by
- // this processor.
- for (types::global_dof_index i=0; i<dof2.n_dofs(); ++i)
- if (locally_owned_dofs.is_element(i))
- {
- Assert(touch_count(i)!=0, ExcInternalError());
- u2(i) /= touch_count(i);
- }
-
- // finish the work on parallel vectors
- u2.compress(VectorOperation::insert);
- // Apply hanging node constraints.
- constraints.distribute(u2);
- }
-
-
-
- template <int dim, class InVector, class OutVector, int spacedim>
- void
- back_interpolate(const DoFHandler<dim,spacedim> &dof1,
- const InVector &u1,
- const FiniteElement<dim,spacedim> &fe2,
- OutVector &u1_interpolated)
- {
- Assert(dof1.get_fe().n_components() == fe2.n_components(),
- ExcDimensionMismatch(dof1.get_fe().n_components(), fe2.n_components()));
- Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
- Assert(u1_interpolated.size()==dof1.n_dofs(),
- ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
-
-#ifdef DEAL_II_WITH_PETSC
- if (dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1) != 0)
- if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
- {
- // if u1 is a parallel distributed
- // PETSc vector, we check the local
- // size of u1 for safety
- Assert(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size() == dof1.locally_owned_dofs().n_elements(),
- ExcDimensionMismatch(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size(), dof1.locally_owned_dofs().n_elements()));
- };
-
- if (dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated) != 0)
- if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
- {
- Assert(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated)->local_size() == dof1.locally_owned_dofs().n_elements(),
- ExcDimensionMismatch(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated)->local_size(), dof1.locally_owned_dofs().n_elements()));
- };
-#endif
-
- // For continuous elements on grids
- // with hanging nodes we need
- // hanging node
- // constraints. Consequently, when
- // the elements are continuous no
- // hanging node constraints are
- // allowed.
- const bool hanging_nodes_not_allowed=
- (dof1.get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
-
- const unsigned int dofs_per_cell1=dof1.get_fe().dofs_per_cell;
-
- Vector<typename OutVector::value_type> u1_local(dofs_per_cell1);
- Vector<typename OutVector::value_type> u1_int_local(dofs_per_cell1);
-
- const types::subdomain_id subdomain_id =
- dof1.get_tria().locally_owned_subdomain();
-
- typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof1.begin_active(),
- endc = dof1.end();
-
- FullMatrix<double> interpolation_matrix(dofs_per_cell1, dofs_per_cell1);
- get_back_interpolation_matrix(dof1.get_fe(), fe2,
- interpolation_matrix);
- for (; cell!=endc; ++cell)
- if ((cell->subdomain_id() == subdomain_id)
- ||
- (subdomain_id == numbers::invalid_subdomain_id))
- {
- if (hanging_nodes_not_allowed)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- Assert (cell->at_boundary(face) ||
- cell->neighbor(face)->level() == cell->level(),
- ExcHangingNodesNotAllowed(0));
-
- cell->get_dof_values(u1, u1_local);
- interpolation_matrix.vmult(u1_int_local, u1_local);
- cell->set_dof_values(u1_int_local, u1_interpolated);
- }
-
- // if we work on a parallel PETSc vector
- // we have to finish the work
- u1_interpolated.compress(VectorOperation::insert);
- }
-
-
-
- template <int dim,
- template <int> class DH,
- class InVector, class OutVector, int spacedim>
- void
- back_interpolate(const DH<dim> &dof1,
- const InVector &u1,
- const FiniteElement<dim,spacedim> &fe2,
- OutVector &u1_interpolated)
- {
- Assert(u1.size() == dof1.n_dofs(),
- ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
- Assert(u1_interpolated.size() == dof1.n_dofs(),
- ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
-
-#ifdef DEAL_II_WITH_PETSC
- if (dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1) != 0)
- if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
- {
- // if u1 is a parallel distributed
- // PETSc vector, we check the local
- // size of u1 for safety
- Assert(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size() == dof1.locally_owned_dofs().n_elements(),
- ExcDimensionMismatch(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size(), dof1.locally_owned_dofs().n_elements()));
- };
-
- if (dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated) != 0)
- if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
- {
- Assert(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated)->local_size() == dof1.locally_owned_dofs().n_elements(),
- ExcDimensionMismatch(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated)->local_size(), dof1.locally_owned_dofs().n_elements()));
- };
-#endif
-
- Vector<typename OutVector::value_type> u1_local(DoFTools::max_dofs_per_cell(dof1));
- Vector<typename OutVector::value_type> u1_int_local(DoFTools::max_dofs_per_cell(dof1));
-
- const types::subdomain_id subdomain_id =
- dof1.get_tria().locally_owned_subdomain();
-
- typename DH<dim>::active_cell_iterator cell = dof1.begin_active(),
- endc = dof1.end();
-
- // map from possible fe objects in
- // dof1 to the back_interpolation
- // matrices
- std::map<const FiniteElement<dim> *,
- std_cxx1x::shared_ptr<FullMatrix<double> > > interpolation_matrices;
-
- for (; cell!=endc; ++cell)
- if ((cell->subdomain_id() == subdomain_id)
- ||
- (subdomain_id == numbers::invalid_subdomain_id))
- {
- Assert(cell->get_fe().n_components() == fe2.n_components(),
- ExcDimensionMismatch(cell->get_fe().n_components(),
- fe2.n_components()));
-
- // For continuous elements on
- // grids with hanging nodes we
- // need hanging node
- // constraints. Consequently,
- // when the elements are
- // continuous no hanging node
- // constraints are allowed.
- const bool hanging_nodes_not_allowed=
- (cell->get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
-
- if (hanging_nodes_not_allowed)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- Assert (cell->at_boundary(face) ||
- cell->neighbor(face)->level() == cell->level(),
- ExcHangingNodesNotAllowed(0));
-
- const unsigned int dofs_per_cell1 = cell->get_fe().dofs_per_cell;
-
- // make sure back_interpolation
- // matrix is available
- if (interpolation_matrices[&cell->get_fe()] != 0)
- {
- interpolation_matrices[&cell->get_fe()] =
- std_cxx1x::shared_ptr<FullMatrix<double> >
- (new FullMatrix<double>(dofs_per_cell1, dofs_per_cell1));
- get_back_interpolation_matrix(dof1.get_fe(), fe2,
- *interpolation_matrices[&cell->get_fe()]);
- }
-
- u1_local.reinit (dofs_per_cell1);
- u1_int_local.reinit (dofs_per_cell1);
-
- cell->get_dof_values(u1, u1_local);
- interpolation_matrices[&cell->get_fe()]->vmult(u1_int_local, u1_local);
- cell->set_dof_values(u1_int_local, u1_interpolated);
- };
-
- // if we work on a parallel PETSc vector
- // we have to finish the work
- u1_interpolated.compress(VectorOperation::insert);
- }
-
-
-
- namespace internal
- {
- namespace
- {
- template <int dim, int spacedim, class InVector>
- void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
- const ConstraintMatrix &constraints1,
- const InVector &u1,
- const DoFHandler<dim,spacedim> &dof2,
- const ConstraintMatrix &constraints2,
- InVector &u1_interpolated)
- {
- Vector<typename InVector::value_type> u2(dof2.n_dofs());
- interpolate(dof1, u1, dof2, constraints2, u2);
- interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
- }
-
- // special version for PETSc
-#ifdef DEAL_II_WITH_PETSC
- template <int dim, int spacedim>
- void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
- const ConstraintMatrix &constraints1,
- const PETScWrappers::MPI::Vector &u1,
- const DoFHandler<dim,spacedim> &dof2,
- const ConstraintMatrix &constraints2,
- PETScWrappers::MPI::Vector &u1_interpolated)
- {
- // if u1 is a parallel distributed PETSc vector, we create a
- // vector u2 with based on the sets of locally owned and relevant
- // dofs of dof2
- IndexSet dof2_locally_owned_dofs = dof2.locally_owned_dofs();
- IndexSet dof2_locally_relevant_dofs;
- DoFTools::extract_locally_relevant_dofs (dof2,
- dof2_locally_relevant_dofs);
-
- PETScWrappers::MPI::Vector u2_out (u1.get_mpi_communicator(),
- dof2_locally_owned_dofs);
- interpolate(dof1, u1, dof2, constraints2, u2_out);
- PETScWrappers::MPI::Vector u2 (u1.get_mpi_communicator(),
- dof2_locally_owned_dofs,
- dof2_locally_relevant_dofs);
- u2 = u2_out;
- interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
- }
-#endif
-
- // special version for parallel::distributed::Vector
- template <int dim, int spacedim, typename Number>
- void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
- const ConstraintMatrix &constraints1,
- const parallel::distributed::Vector<Number> &u1,
- const DoFHandler<dim,spacedim> &dof2,
- const ConstraintMatrix &constraints2,
- parallel::distributed::Vector<Number> &u1_interpolated)
- {
- IndexSet dof2_locally_owned_dofs = dof2.locally_owned_dofs();
- IndexSet dof2_locally_relevant_dofs;
- DoFTools::extract_locally_relevant_dofs (dof2,
- dof2_locally_relevant_dofs);
-
- parallel::distributed::Vector<Number>
- u2 (dof2_locally_owned_dofs,
- dof2_locally_relevant_dofs,
- u1.get_mpi_communicator());
-
- interpolate(dof1, u1, dof2, constraints2, u2);
- u2.update_ghost_values ();
- interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
- }
- }
- }
-
-
- template <int dim, class InVector, class OutVector, int spacedim>
- void back_interpolate(const DoFHandler<dim,spacedim> &dof1,
- const ConstraintMatrix &constraints1,
- const InVector &u1,
- const DoFHandler<dim,spacedim> &dof2,
- const ConstraintMatrix &constraints2,
- OutVector &u1_interpolated)
- {
- // For discontinuous elements without constraints take the simpler version
- // of the back_interpolate function.
- if (dof1.get_fe().dofs_per_vertex==0 && dof2.get_fe().dofs_per_vertex==0
- && constraints1.n_constraints()==0 && constraints2.n_constraints()==0)
- back_interpolate(dof1, u1, dof2.get_fe(), u1_interpolated);
- else
- {
- Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
- ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
- Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
- Assert(u1_interpolated.size()==dof1.n_dofs(),
- ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
-
- // For continuous elements first interpolate to dof2, taking into
- // account constraints2, and then interpolate back to dof1 taking into
- // account constraints1
- internal::back_interpolate(dof1, constraints1, u1, dof2, constraints2,
- u1_interpolated);
- }
- }
-
-
-
- template <int dim, class InVector, class OutVector, int spacedim>
- void interpolation_difference (const DoFHandler<dim,spacedim> &dof1,
- const InVector &u1,
- const FiniteElement<dim,spacedim> &fe2,
- OutVector &u1_difference)
- {
- Assert(dof1.get_fe().n_components() == fe2.n_components(),
- ExcDimensionMismatch(dof1.get_fe().n_components(), fe2.n_components()));
- Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
- Assert(u1_difference.size()==dof1.n_dofs(),
- ExcDimensionMismatch(u1_difference.size(), dof1.n_dofs()));
-
-#ifdef DEAL_II_WITH_PETSC
- if (dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1) != 0)
- if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
- {
- // if u1 is a parallel distributed
- // PETSc vector, we check the local
- // size of u1 for safety
- Assert(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size() == dof1.locally_owned_dofs().n_elements(),
- ExcDimensionMismatch(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size(), dof1.locally_owned_dofs().n_elements()));
- };
-
- if (dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_difference) != 0)
- if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
- {
- Assert(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_difference)->local_size() == dof1.locally_owned_dofs().n_elements(),
- ExcDimensionMismatch(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_difference)->local_size(), dof1.locally_owned_dofs().n_elements()));
- };
-#endif
-
- // For continuous elements on grids
- // with hanging nodes we need
- // hanging node
- // constraints. Consequently, when
- // the elements are continuous no
- // hanging node constraints are
- // allowed.
- const bool hanging_nodes_not_allowed=
- (dof1.get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
-
- const unsigned int dofs_per_cell=dof1.get_fe().dofs_per_cell;
-
- Vector<typename OutVector::value_type> u1_local(dofs_per_cell);
- Vector<typename OutVector::value_type> u1_diff_local(dofs_per_cell);
-
- const types::subdomain_id subdomain_id =
- dof1.get_tria().locally_owned_subdomain();
-
- FullMatrix<double> difference_matrix(dofs_per_cell, dofs_per_cell);
- get_interpolation_difference_matrix(dof1.get_fe(), fe2,
- difference_matrix);
-
- typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof1.begin_active(),
- endc = dof1.end();
-
- for (; cell!=endc; ++cell)
- if ((cell->subdomain_id() == subdomain_id)
- ||
- (subdomain_id == numbers::invalid_subdomain_id))
- {
- if (hanging_nodes_not_allowed)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- Assert (cell->at_boundary(face) ||
- cell->neighbor(face)->level() == cell->level(),
- ExcHangingNodesNotAllowed(0));
-
- cell->get_dof_values(u1, u1_local);
- difference_matrix.vmult(u1_diff_local, u1_local);
- cell->set_dof_values(u1_diff_local, u1_difference);
- }
-
- // if we work on a parallel PETSc vector
- // we have to finish the work and
- // update ghost values
- u1_difference.compress(VectorOperation::insert);
- }
-
-
-
- template <int dim, class InVector, class OutVector, int spacedim>
- void interpolation_difference(const DoFHandler<dim,spacedim> &dof1,
- const ConstraintMatrix &constraints1,
- const InVector &u1,
- const DoFHandler<dim,spacedim> &dof2,
- const ConstraintMatrix &constraints2,
- OutVector &u1_difference)
- {
- // For discontinuous elements
- // without constraints take the
- // cheaper version of the
- // interpolation_difference function.
- if (dof1.get_fe().dofs_per_vertex==0 && dof2.get_fe().dofs_per_vertex==0
- && constraints1.n_constraints()==0 && constraints2.n_constraints()==0)
- interpolation_difference(dof1, u1, dof2.get_fe(), u1_difference);
- else
- {
- back_interpolate(dof1, constraints1, u1, dof2, constraints2, u1_difference);
- u1_difference.sadd(-1, u1);
- }
- }
-
-
-
- template <int dim, class InVector, class OutVector, int spacedim>
- void project_dg(const DoFHandler<dim,spacedim> &dof1,
- const InVector &u1,
- const DoFHandler<dim,spacedim> &dof2,
- OutVector &u2)
- {
- Assert(&dof1.get_tria()==&dof2.get_tria(), ExcTriangulationMismatch());
- Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
- ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
- Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
- Assert(u2.size()==dof2.n_dofs(), ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
-
- typename DoFHandler<dim,spacedim>::active_cell_iterator cell1 = dof1.begin_active();
- typename DoFHandler<dim,spacedim>::active_cell_iterator cell2 = dof2.begin_active();
- typename DoFHandler<dim,spacedim>::active_cell_iterator end = dof2.end();
-
- const unsigned int n1 = dof1.get_fe().dofs_per_cell;
- const unsigned int n2 = dof2.get_fe().dofs_per_cell;
-
- Vector<double> u1_local(n1);
- Vector<double> u2_local(n2);
- std::vector<types::global_dof_index> dofs(n2);
-
- FullMatrix<double> matrix(n2,n1);
- get_projection_matrix(dof1.get_fe(), dof2.get_fe(), matrix);
-
- while (cell2 != end)
- {
- cell1->get_dof_values(u1, u1_local);
- matrix.vmult(u2_local, u1_local);
- cell2->get_dof_indices(dofs);
- for (unsigned int i=0; i<n2; ++i)
- {
- u2(dofs[i])+=u2_local(i);
- }
-
- ++cell1;
- ++cell2;
- }
- }
-
-
- template <int dim, class InVector, class OutVector, int spacedim>
- void extrapolate(const DoFHandler<dim,spacedim> &dof1,
- const InVector &u1,
- const DoFHandler<dim,spacedim> &dof2,
- OutVector &u2)
- {
- ConstraintMatrix dummy;
- dummy.close();
- extrapolate(dof1, u1, dof2, dummy, u2);
- }
-
-
-
- template <int dim, class InVector, class OutVector, int spacedim>
- void extrapolate(const DoFHandler<dim,spacedim> &dof1,
- const InVector &u1,
- const DoFHandler<dim,spacedim> &dof2,
- const ConstraintMatrix &constraints,
- OutVector &u2)
- {
- Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
- ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
- Assert(&dof1.get_tria()==&dof2.get_tria(), ExcTriangulationMismatch());
- Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
- Assert(u2.size()==dof2.n_dofs(), ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
-
- OutVector u3;
- u3.reinit(u2);
- interpolate(dof1, u1, dof2, constraints, u3);
-
- const unsigned int dofs_per_cell = dof2.get_fe().dofs_per_cell;
- Vector<typename OutVector::value_type> dof_values(dofs_per_cell);
-
- // make sure that each cell on the
- // coarsest level is at least once
- // refined. otherwise, we can't
- // treat these cells and would
- // generate a bogus result
- {
- typename DoFHandler<dim,spacedim>::cell_iterator cell = dof2.begin(0),
- endc = dof2.end(0);
- for (; cell!=endc; ++cell)
- Assert (cell->has_children(), ExcGridNotRefinedAtLeastOnce());
- }
-
- // then traverse grid bottom up
- for (unsigned int level=0; level<dof1.get_tria().n_levels()-1; ++level)
- {
- typename DoFHandler<dim,spacedim>::cell_iterator cell=dof2.begin(level),
- endc=dof2.end(level);
-
- for (; cell!=endc; ++cell)
- if (!cell->active())
- {
- // check whether this
- // cell has active
- // children
- bool active_children=false;
- for (unsigned int child_n=0; child_n<cell->n_children(); ++child_n)
- if (cell->child(child_n)->active())
- {
- active_children=true;
- break;
- }
-
- // if there are active
- // children, the we have
- // to work on this
- // cell. get the data
- // from the one vector
- // and set it on the
- // other
- if (active_children)
- {
- cell->get_interpolated_dof_values(u3, dof_values);
- cell->set_dof_values_by_interpolation(dof_values, u2);
- }
- }
- }
-
- // Apply hanging node constraints.
- constraints.distribute(u2);
- }
-
template <>
void
return Utilities::invert_permutation(hierarchic_to_lexicographic_numbering (fe));
}
-}
+} // end of namespace FETools
// ---------------------------------------------------------------------
-
-for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; Vector : SERIAL_VECTORS)
- {
- namespace FETools
- \{
-#if deal_II_dimension <= deal_II_space_dimension
- template
- void interpolate<deal_II_dimension,deal_II_space_dimension>
- (const DoFHandler<deal_II_dimension,deal_II_space_dimension> &, const Vector &,
- const DoFHandler<deal_II_dimension,deal_II_space_dimension> &, Vector &);
-
- template
- void interpolate<deal_II_dimension,deal_II_space_dimension>
- (const DoFHandler<deal_II_dimension,deal_II_space_dimension> &, const Vector &,
- const DoFHandler<deal_II_dimension,deal_II_space_dimension> &, const ConstraintMatrix &,
- Vector &);
-#endif
- \}
- }
-
for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
{
namespace FETools
{
namespace FETools
\{
+
+#if deal_II_dimension <= deal_II_space_dimension
+ template
+ void get_interpolation_matrix<deal_II_dimension,double,deal_II_space_dimension>
+ (const FiniteElement<deal_II_dimension,deal_II_space_dimension> &,
+ const FiniteElement<deal_II_dimension,deal_II_space_dimension> &,
+ FullMatrix<double> &);
+#endif
+
#if deal_II_dimension == deal_II_space_dimension
template class FEFactoryBase<deal_II_dimension>;
void compute_component_wise(
const FiniteElement<deal_II_dimension>& ,
std::vector<unsigned int>&, std::vector<std::vector<unsigned int> >&);
- template
-
- void get_interpolation_matrix<deal_II_dimension>
- (const FiniteElement<deal_II_dimension> &,
- const FiniteElement<deal_II_dimension> &,
- FullMatrix<double> &);
+
template
void get_back_interpolation_matrix<deal_II_dimension>
(const FiniteElement<deal_II_dimension> &,
(const FiniteElement<deal_II_dimension> &, FullMatrix<double> (&)[GeometryInfo<deal_II_dimension>::max_children_per_face],
unsigned int, unsigned int);
- template
- void interpolate<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension> &, const Vector<double> &,
- const hp::DoFHandler<deal_II_dimension> &, Vector<double> &);
- template
- void interpolate<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension> &, const Vector<double> &,
- const hp::DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
- Vector<double> &);
- template
- void interpolate<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension> &, const Vector<float> &,
- const hp::DoFHandler<deal_II_dimension> &, Vector<float> &);
- template
- void interpolate<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension> &, const Vector<float> &,
- const hp::DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
- Vector<float> &);
-
template FiniteElement<deal_II_dimension,deal_II_dimension> *
get_fe_from_name<deal_II_dimension> (const std::string &);
#endif
\}
}
-
-
-
-for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; VEC : SERIAL_VECTORS)
- {
- namespace FETools
- \{
-#if deal_II_dimension == deal_II_space_dimension
- template
- void back_interpolate<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &, const VEC &,
- const FiniteElement<deal_II_dimension> &, VEC &);
- template
- void back_interpolate<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
- const VEC &,
- const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
- VEC &);
- template
- void interpolation_difference<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &, const VEC &,
- const FiniteElement<deal_II_dimension> &, VEC &);
- template
- void interpolation_difference<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
- const VEC &,
- const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
- VEC &);
- template
- void project_dg<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &, const VEC &,
- const DoFHandler<deal_II_dimension> &, VEC &);
- template
- void extrapolate<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &, const VEC &,
- const DoFHandler<deal_II_dimension> &, VEC &);
- template
- void extrapolate<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &, const VEC &,
- const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
- VEC &);
-#endif
- \}
- }
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/qprojector.h>
+#include <deal.II/base/thread_management.h>
+#include <deal.II/base/utilities.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_parallel_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/petsc_parallel_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/fe/fe_tools.h>
+#include <deal.II/fe/fe.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/hp/dof_handler.h>
+
+#include <deal.II/base/std_cxx1x/shared_ptr.h>
+
+#include <deal.II/base/index_set.h>
+
+#include <iostream>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+namespace FETools
+{
+ template <int dim, int spacedim,
+ template <int, int> class DH1,
+ template <int, int> class DH2,
+ class InVector, class OutVector>
+ void
+ interpolate(const DH1<dim, spacedim> &dof1,
+ const InVector &u1,
+ const DH2<dim, spacedim> &dof2,
+ OutVector &u2)
+ {
+ ConstraintMatrix dummy;
+ dummy.close();
+ interpolate(dof1, u1, dof2, dummy, u2);
+ }
+
+
+
+ template <int dim, int spacedim,
+ template <int, int> class DH1,
+ template <int, int> class DH2,
+ class InVector, class OutVector>
+ void
+ interpolate (const DH1<dim, spacedim> &dof1,
+ const InVector &u1,
+ const DH2<dim, spacedim> &dof2,
+ const ConstraintMatrix &constraints,
+ OutVector &u2)
+ {
+ Assert(&dof1.get_tria()==&dof2.get_tria(), ExcTriangulationMismatch());
+
+ Assert(u1.size()==dof1.n_dofs(),
+ ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
+ Assert(u2.size()==dof2.n_dofs(),
+ ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
+
+#ifdef DEAL_II_WITH_PETSC
+ if (dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1) != 0)
+ if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
+ {
+ // if u1 is a parallel distributed
+ // PETSc vector, we check the local
+ // size of u1 for safety
+ Assert(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size() == dof1.locally_owned_dofs().n_elements(),
+ ExcDimensionMismatch(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size(), dof1.locally_owned_dofs().n_elements()));
+ };
+
+ if (dynamic_cast<PETScWrappers::MPI::Vector *>(&u2) != 0)
+ if (dynamic_cast<const DoFHandler<dim>*>(&dof2) != 0)
+ {
+ Assert(dynamic_cast<PETScWrappers::MPI::Vector *>(&u2)->local_size() == dof2.locally_owned_dofs().n_elements(),
+ ExcDimensionMismatch(dynamic_cast<PETScWrappers::MPI::Vector *>(&u2)->local_size(), dof2.locally_owned_dofs().n_elements()));
+ };
+#endif
+ // allocate vectors at maximal
+ // size. will be reinited in inner
+ // cell, but Vector makes sure that
+ // this does not lead to
+ // reallocation of memory
+ Vector<typename OutVector::value_type> u1_local(DoFTools::max_dofs_per_cell(dof1));
+ Vector<typename OutVector::value_type> u2_local(DoFTools::max_dofs_per_cell(dof2));
+
+ // have a map for interpolation
+ // matrices. shared_ptr make sure
+ // that memory is released again
+ std::map<const FiniteElement<dim,spacedim> *,
+ std::map<const FiniteElement<dim,spacedim> *,
+ std_cxx1x::shared_ptr<FullMatrix<double> > > >
+ interpolation_matrices;
+
+ typename DH1<dim,spacedim>::active_cell_iterator cell1 = dof1.begin_active(),
+ endc1 = dof1.end();
+ typename DH2<dim,spacedim>::active_cell_iterator cell2 = dof2.begin_active(),
+ endc2 = dof2.end();
+
+ std::vector<types::global_dof_index> dofs;
+ dofs.reserve (DoFTools::max_dofs_per_cell (dof2));
+
+ u2 = 0;
+ OutVector touch_count(u2);
+ touch_count = 0;
+
+ // for distributed triangulations,
+ // we can only interpolate u1 on
+ // a cell, which this processor owns,
+ // so we have to know the subdomain_id
+ const types::subdomain_id subdomain_id =
+ dof1.get_tria().locally_owned_subdomain();
+
+ for (; cell1!=endc1; ++cell1, ++cell2)
+ if ((cell1->subdomain_id() == subdomain_id)
+ ||
+ (subdomain_id == numbers::invalid_subdomain_id))
+ {
+ Assert(cell1->get_fe().n_components() == cell2->get_fe().n_components(),
+ ExcDimensionMismatch (cell1->get_fe().n_components(),
+ cell2->get_fe().n_components()));
+
+ // for continuous elements on
+ // grids with hanging nodes we
+ // need hanging node
+ // constraints. Consequentely,
+ // if there are no constraints
+ // then hanging nodes are not
+ // allowed.
+ const bool hanging_nodes_not_allowed
+ = ((cell2->get_fe().dofs_per_vertex != 0) &&
+ (constraints.n_constraints() == 0));
+
+ if (hanging_nodes_not_allowed)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ Assert (cell1->at_boundary(face) ||
+ cell1->neighbor(face)->level() == cell1->level(),
+ ExcHangingNodesNotAllowed(0));
+
+
+ const unsigned int dofs_per_cell1 = cell1->get_fe().dofs_per_cell;
+ const unsigned int dofs_per_cell2 = cell2->get_fe().dofs_per_cell;
+ u1_local.reinit (dofs_per_cell1);
+ u2_local.reinit (dofs_per_cell2);
+
+ // check if interpolation
+ // matrix for this particular
+ // pair of elements is already
+ // there
+ if (interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()].get() == 0)
+ {
+ std_cxx1x::shared_ptr<FullMatrix<double> >
+ interpolation_matrix (new FullMatrix<double> (dofs_per_cell2,
+ dofs_per_cell1));
+ interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()]
+ = interpolation_matrix;
+
+ get_interpolation_matrix(cell1->get_fe(),
+ cell2->get_fe(),
+ *interpolation_matrix);
+ }
+
+ cell1->get_dof_values(u1, u1_local);
+ interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()]
+ ->vmult(u2_local, u1_local);
+
+ dofs.resize (dofs_per_cell2);
+ cell2->get_dof_indices(dofs);
+
+ for (unsigned int i=0; i<dofs_per_cell2; ++i)
+ {
+ u2(dofs[i])+=u2_local(i);
+ touch_count(dofs[i]) += 1;
+ }
+ }
+ // cell1 is at the end, so should
+ // be cell2
+ Assert (cell2 == endc2, ExcInternalError());
+
+ u2.compress(VectorOperation::add);
+ touch_count.compress(VectorOperation::add);
+
+ // if we work on parallel distributed
+ // vectors, we have to ensure, that we only
+ // work on dofs this processor owns.
+ IndexSet locally_owned_dofs = dof2.locally_owned_dofs();
+
+ // when a discontinuous element is
+ // interpolated to a continuous
+ // one, we take the mean values.
+ // for parallel vectors check,
+ // if this component is owned by
+ // this processor.
+ for (types::global_dof_index i=0; i<dof2.n_dofs(); ++i)
+ if (locally_owned_dofs.is_element(i))
+ {
+ Assert(touch_count(i)!=0, ExcInternalError());
+ u2(i) /= touch_count(i);
+ }
+
+ // finish the work on parallel vectors
+ u2.compress(VectorOperation::insert);
+ // Apply hanging node constraints.
+ constraints.distribute(u2);
+ }
+
+
+
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void
+ back_interpolate(const DoFHandler<dim,spacedim> &dof1,
+ const InVector &u1,
+ const FiniteElement<dim,spacedim> &fe2,
+ OutVector &u1_interpolated)
+ {
+ Assert(dof1.get_fe().n_components() == fe2.n_components(),
+ ExcDimensionMismatch(dof1.get_fe().n_components(), fe2.n_components()));
+ Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
+ Assert(u1_interpolated.size()==dof1.n_dofs(),
+ ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
+
+#ifdef DEAL_II_WITH_PETSC
+ if (dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1) != 0)
+ if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
+ {
+ // if u1 is a parallel distributed
+ // PETSc vector, we check the local
+ // size of u1 for safety
+ Assert(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size() == dof1.locally_owned_dofs().n_elements(),
+ ExcDimensionMismatch(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size(), dof1.locally_owned_dofs().n_elements()));
+ };
+
+ if (dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated) != 0)
+ if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
+ {
+ Assert(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated)->local_size() == dof1.locally_owned_dofs().n_elements(),
+ ExcDimensionMismatch(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated)->local_size(), dof1.locally_owned_dofs().n_elements()));
+ };
+#endif
+
+ // For continuous elements on grids
+ // with hanging nodes we need
+ // hanging node
+ // constraints. Consequently, when
+ // the elements are continuous no
+ // hanging node constraints are
+ // allowed.
+ const bool hanging_nodes_not_allowed=
+ (dof1.get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
+
+ const unsigned int dofs_per_cell1=dof1.get_fe().dofs_per_cell;
+
+ Vector<typename OutVector::value_type> u1_local(dofs_per_cell1);
+ Vector<typename OutVector::value_type> u1_int_local(dofs_per_cell1);
+
+ const types::subdomain_id subdomain_id =
+ dof1.get_tria().locally_owned_subdomain();
+
+ typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof1.begin_active(),
+ endc = dof1.end();
+
+ FullMatrix<double> interpolation_matrix(dofs_per_cell1, dofs_per_cell1);
+ get_back_interpolation_matrix(dof1.get_fe(), fe2,
+ interpolation_matrix);
+ for (; cell!=endc; ++cell)
+ if ((cell->subdomain_id() == subdomain_id)
+ ||
+ (subdomain_id == numbers::invalid_subdomain_id))
+ {
+ if (hanging_nodes_not_allowed)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ Assert (cell->at_boundary(face) ||
+ cell->neighbor(face)->level() == cell->level(),
+ ExcHangingNodesNotAllowed(0));
+
+ cell->get_dof_values(u1, u1_local);
+ interpolation_matrix.vmult(u1_int_local, u1_local);
+ cell->set_dof_values(u1_int_local, u1_interpolated);
+ }
+
+ // if we work on a parallel PETSc vector
+ // we have to finish the work
+ u1_interpolated.compress(VectorOperation::insert);
+ }
+
+
+
+ template <int dim,
+ template <int> class DH,
+ class InVector, class OutVector, int spacedim>
+ void
+ back_interpolate(const DH<dim> &dof1,
+ const InVector &u1,
+ const FiniteElement<dim,spacedim> &fe2,
+ OutVector &u1_interpolated)
+ {
+ Assert(u1.size() == dof1.n_dofs(),
+ ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
+ Assert(u1_interpolated.size() == dof1.n_dofs(),
+ ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
+
+#ifdef DEAL_II_WITH_PETSC
+ if (dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1) != 0)
+ if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
+ {
+ // if u1 is a parallel distributed
+ // PETSc vector, we check the local
+ // size of u1 for safety
+ Assert(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size() == dof1.locally_owned_dofs().n_elements(),
+ ExcDimensionMismatch(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size(), dof1.locally_owned_dofs().n_elements()));
+ };
+
+ if (dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated) != 0)
+ if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
+ {
+ Assert(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated)->local_size() == dof1.locally_owned_dofs().n_elements(),
+ ExcDimensionMismatch(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_interpolated)->local_size(), dof1.locally_owned_dofs().n_elements()));
+ };
+#endif
+
+ Vector<typename OutVector::value_type> u1_local(DoFTools::max_dofs_per_cell(dof1));
+ Vector<typename OutVector::value_type> u1_int_local(DoFTools::max_dofs_per_cell(dof1));
+
+ const types::subdomain_id subdomain_id =
+ dof1.get_tria().locally_owned_subdomain();
+
+ typename DH<dim>::active_cell_iterator cell = dof1.begin_active(),
+ endc = dof1.end();
+
+ // map from possible fe objects in
+ // dof1 to the back_interpolation
+ // matrices
+ std::map<const FiniteElement<dim> *,
+ std_cxx1x::shared_ptr<FullMatrix<double> > > interpolation_matrices;
+
+ for (; cell!=endc; ++cell)
+ if ((cell->subdomain_id() == subdomain_id)
+ ||
+ (subdomain_id == numbers::invalid_subdomain_id))
+ {
+ Assert(cell->get_fe().n_components() == fe2.n_components(),
+ ExcDimensionMismatch(cell->get_fe().n_components(),
+ fe2.n_components()));
+
+ // For continuous elements on
+ // grids with hanging nodes we
+ // need hanging node
+ // constraints. Consequently,
+ // when the elements are
+ // continuous no hanging node
+ // constraints are allowed.
+ const bool hanging_nodes_not_allowed=
+ (cell->get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
+
+ if (hanging_nodes_not_allowed)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ Assert (cell->at_boundary(face) ||
+ cell->neighbor(face)->level() == cell->level(),
+ ExcHangingNodesNotAllowed(0));
+
+ const unsigned int dofs_per_cell1 = cell->get_fe().dofs_per_cell;
+
+ // make sure back_interpolation
+ // matrix is available
+ if (interpolation_matrices[&cell->get_fe()] != 0)
+ {
+ interpolation_matrices[&cell->get_fe()] =
+ std_cxx1x::shared_ptr<FullMatrix<double> >
+ (new FullMatrix<double>(dofs_per_cell1, dofs_per_cell1));
+ get_back_interpolation_matrix(dof1.get_fe(), fe2,
+ *interpolation_matrices[&cell->get_fe()]);
+ }
+
+ u1_local.reinit (dofs_per_cell1);
+ u1_int_local.reinit (dofs_per_cell1);
+
+ cell->get_dof_values(u1, u1_local);
+ interpolation_matrices[&cell->get_fe()]->vmult(u1_int_local, u1_local);
+ cell->set_dof_values(u1_int_local, u1_interpolated);
+ };
+
+ // if we work on a parallel PETSc vector
+ // we have to finish the work
+ u1_interpolated.compress(VectorOperation::insert);
+ }
+
+
+
+ namespace internal
+ {
+ namespace
+ {
+ template <int dim, int spacedim, class InVector>
+ void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
+ const ConstraintMatrix &constraints1,
+ const InVector &u1,
+ const DoFHandler<dim,spacedim> &dof2,
+ const ConstraintMatrix &constraints2,
+ InVector &u1_interpolated)
+ {
+ Vector<typename InVector::value_type> u2(dof2.n_dofs());
+ interpolate(dof1, u1, dof2, constraints2, u2);
+ interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
+ }
+
+ // special version for PETSc
+#ifdef DEAL_II_WITH_PETSC
+ template <int dim, int spacedim>
+ void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
+ const ConstraintMatrix &constraints1,
+ const PETScWrappers::MPI::Vector &u1,
+ const DoFHandler<dim,spacedim> &dof2,
+ const ConstraintMatrix &constraints2,
+ PETScWrappers::MPI::Vector &u1_interpolated)
+ {
+ // if u1 is a parallel distributed PETSc vector, we create a
+ // vector u2 with based on the sets of locally owned and relevant
+ // dofs of dof2
+ IndexSet dof2_locally_owned_dofs = dof2.locally_owned_dofs();
+ IndexSet dof2_locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs (dof2,
+ dof2_locally_relevant_dofs);
+
+ PETScWrappers::MPI::Vector u2_out (u1.get_mpi_communicator(),
+ dof2_locally_owned_dofs);
+ interpolate(dof1, u1, dof2, constraints2, u2_out);
+ PETScWrappers::MPI::Vector u2 (u1.get_mpi_communicator(),
+ dof2_locally_owned_dofs,
+ dof2_locally_relevant_dofs);
+ u2 = u2_out;
+ interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
+ }
+#endif
+
+ // special version for parallel::distributed::Vector
+ template <int dim, int spacedim, typename Number>
+ void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
+ const ConstraintMatrix &constraints1,
+ const parallel::distributed::Vector<Number> &u1,
+ const DoFHandler<dim,spacedim> &dof2,
+ const ConstraintMatrix &constraints2,
+ parallel::distributed::Vector<Number> &u1_interpolated)
+ {
+ IndexSet dof2_locally_owned_dofs = dof2.locally_owned_dofs();
+ IndexSet dof2_locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs (dof2,
+ dof2_locally_relevant_dofs);
+
+ parallel::distributed::Vector<Number>
+ u2 (dof2_locally_owned_dofs,
+ dof2_locally_relevant_dofs,
+ u1.get_mpi_communicator());
+
+ interpolate(dof1, u1, dof2, constraints2, u2);
+ u2.update_ghost_values ();
+ interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
+ }
+ }
+ }
+
+
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void back_interpolate(const DoFHandler<dim,spacedim> &dof1,
+ const ConstraintMatrix &constraints1,
+ const InVector &u1,
+ const DoFHandler<dim,spacedim> &dof2,
+ const ConstraintMatrix &constraints2,
+ OutVector &u1_interpolated)
+ {
+ // For discontinuous elements without constraints take the simpler version
+ // of the back_interpolate function.
+ if (dof1.get_fe().dofs_per_vertex==0 && dof2.get_fe().dofs_per_vertex==0
+ && constraints1.n_constraints()==0 && constraints2.n_constraints()==0)
+ back_interpolate(dof1, u1, dof2.get_fe(), u1_interpolated);
+ else
+ {
+ Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
+ ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
+ Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
+ Assert(u1_interpolated.size()==dof1.n_dofs(),
+ ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
+
+ // For continuous elements first interpolate to dof2, taking into
+ // account constraints2, and then interpolate back to dof1 taking into
+ // account constraints1
+ internal::back_interpolate(dof1, constraints1, u1, dof2, constraints2,
+ u1_interpolated);
+ }
+ }
+
+
+
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void interpolation_difference (const DoFHandler<dim,spacedim> &dof1,
+ const InVector &u1,
+ const FiniteElement<dim,spacedim> &fe2,
+ OutVector &u1_difference)
+ {
+ Assert(dof1.get_fe().n_components() == fe2.n_components(),
+ ExcDimensionMismatch(dof1.get_fe().n_components(), fe2.n_components()));
+ Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
+ Assert(u1_difference.size()==dof1.n_dofs(),
+ ExcDimensionMismatch(u1_difference.size(), dof1.n_dofs()));
+
+#ifdef DEAL_II_WITH_PETSC
+ if (dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1) != 0)
+ if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
+ {
+ // if u1 is a parallel distributed
+ // PETSc vector, we check the local
+ // size of u1 for safety
+ Assert(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size() == dof1.locally_owned_dofs().n_elements(),
+ ExcDimensionMismatch(dynamic_cast<const PETScWrappers::MPI::Vector *>(&u1)->local_size(), dof1.locally_owned_dofs().n_elements()));
+ };
+
+ if (dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_difference) != 0)
+ if (dynamic_cast<const DoFHandler<dim>*>(&dof1) != 0)
+ {
+ Assert(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_difference)->local_size() == dof1.locally_owned_dofs().n_elements(),
+ ExcDimensionMismatch(dynamic_cast<PETScWrappers::MPI::Vector *>(&u1_difference)->local_size(), dof1.locally_owned_dofs().n_elements()));
+ };
+#endif
+
+ // For continuous elements on grids
+ // with hanging nodes we need
+ // hanging node
+ // constraints. Consequently, when
+ // the elements are continuous no
+ // hanging node constraints are
+ // allowed.
+ const bool hanging_nodes_not_allowed=
+ (dof1.get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
+
+ const unsigned int dofs_per_cell=dof1.get_fe().dofs_per_cell;
+
+ Vector<typename OutVector::value_type> u1_local(dofs_per_cell);
+ Vector<typename OutVector::value_type> u1_diff_local(dofs_per_cell);
+
+ const types::subdomain_id subdomain_id =
+ dof1.get_tria().locally_owned_subdomain();
+
+ FullMatrix<double> difference_matrix(dofs_per_cell, dofs_per_cell);
+ get_interpolation_difference_matrix(dof1.get_fe(), fe2,
+ difference_matrix);
+
+ typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof1.begin_active(),
+ endc = dof1.end();
+
+ for (; cell!=endc; ++cell)
+ if ((cell->subdomain_id() == subdomain_id)
+ ||
+ (subdomain_id == numbers::invalid_subdomain_id))
+ {
+ if (hanging_nodes_not_allowed)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ Assert (cell->at_boundary(face) ||
+ cell->neighbor(face)->level() == cell->level(),
+ ExcHangingNodesNotAllowed(0));
+
+ cell->get_dof_values(u1, u1_local);
+ difference_matrix.vmult(u1_diff_local, u1_local);
+ cell->set_dof_values(u1_diff_local, u1_difference);
+ }
+
+ // if we work on a parallel PETSc vector
+ // we have to finish the work and
+ // update ghost values
+ u1_difference.compress(VectorOperation::insert);
+ }
+
+
+
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void interpolation_difference(const DoFHandler<dim,spacedim> &dof1,
+ const ConstraintMatrix &constraints1,
+ const InVector &u1,
+ const DoFHandler<dim,spacedim> &dof2,
+ const ConstraintMatrix &constraints2,
+ OutVector &u1_difference)
+ {
+ // For discontinuous elements
+ // without constraints take the
+ // cheaper version of the
+ // interpolation_difference function.
+ if (dof1.get_fe().dofs_per_vertex==0 && dof2.get_fe().dofs_per_vertex==0
+ && constraints1.n_constraints()==0 && constraints2.n_constraints()==0)
+ interpolation_difference(dof1, u1, dof2.get_fe(), u1_difference);
+ else
+ {
+ back_interpolate(dof1, constraints1, u1, dof2, constraints2, u1_difference);
+ u1_difference.sadd(-1, u1);
+ }
+ }
+
+
+
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void project_dg(const DoFHandler<dim,spacedim> &dof1,
+ const InVector &u1,
+ const DoFHandler<dim,spacedim> &dof2,
+ OutVector &u2)
+ {
+ Assert(&dof1.get_tria()==&dof2.get_tria(), ExcTriangulationMismatch());
+ Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
+ ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
+ Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
+ Assert(u2.size()==dof2.n_dofs(), ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
+
+ typename DoFHandler<dim,spacedim>::active_cell_iterator cell1 = dof1.begin_active();
+ typename DoFHandler<dim,spacedim>::active_cell_iterator cell2 = dof2.begin_active();
+ typename DoFHandler<dim,spacedim>::active_cell_iterator end = dof2.end();
+
+ const unsigned int n1 = dof1.get_fe().dofs_per_cell;
+ const unsigned int n2 = dof2.get_fe().dofs_per_cell;
+
+ Vector<double> u1_local(n1);
+ Vector<double> u2_local(n2);
+ std::vector<types::global_dof_index> dofs(n2);
+
+ FullMatrix<double> matrix(n2,n1);
+ get_projection_matrix(dof1.get_fe(), dof2.get_fe(), matrix);
+
+ while (cell2 != end)
+ {
+ cell1->get_dof_values(u1, u1_local);
+ matrix.vmult(u2_local, u1_local);
+ cell2->get_dof_indices(dofs);
+ for (unsigned int i=0; i<n2; ++i)
+ {
+ u2(dofs[i])+=u2_local(i);
+ }
+
+ ++cell1;
+ ++cell2;
+ }
+ }
+
+
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void extrapolate(const DoFHandler<dim,spacedim> &dof1,
+ const InVector &u1,
+ const DoFHandler<dim,spacedim> &dof2,
+ OutVector &u2)
+ {
+ ConstraintMatrix dummy;
+ dummy.close();
+ extrapolate(dof1, u1, dof2, dummy, u2);
+ }
+
+
+
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void extrapolate(const DoFHandler<dim,spacedim> &dof1,
+ const InVector &u1,
+ const DoFHandler<dim,spacedim> &dof2,
+ const ConstraintMatrix &constraints,
+ OutVector &u2)
+ {
+ Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
+ ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
+ Assert(&dof1.get_tria()==&dof2.get_tria(), ExcTriangulationMismatch());
+ Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
+ Assert(u2.size()==dof2.n_dofs(), ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
+
+ OutVector u3;
+ u3.reinit(u2);
+ interpolate(dof1, u1, dof2, constraints, u3);
+
+ const unsigned int dofs_per_cell = dof2.get_fe().dofs_per_cell;
+ Vector<typename OutVector::value_type> dof_values(dofs_per_cell);
+
+ // make sure that each cell on the
+ // coarsest level is at least once
+ // refined. otherwise, we can't
+ // treat these cells and would
+ // generate a bogus result
+ {
+ typename DoFHandler<dim,spacedim>::cell_iterator cell = dof2.begin(0),
+ endc = dof2.end(0);
+ for (; cell!=endc; ++cell)
+ Assert (cell->has_children(), ExcGridNotRefinedAtLeastOnce());
+ }
+
+ // then traverse grid bottom up
+ for (unsigned int level=0; level<dof1.get_tria().n_levels()-1; ++level)
+ {
+ typename DoFHandler<dim,spacedim>::cell_iterator cell=dof2.begin(level),
+ endc=dof2.end(level);
+
+ for (; cell!=endc; ++cell)
+ if (!cell->active())
+ {
+ // check whether this
+ // cell has active
+ // children
+ bool active_children=false;
+ for (unsigned int child_n=0; child_n<cell->n_children(); ++child_n)
+ if (cell->child(child_n)->active())
+ {
+ active_children=true;
+ break;
+ }
+
+ // if there are active
+ // children, the we have
+ // to work on this
+ // cell. get the data
+ // from the one vector
+ // and set it on the
+ // other
+ if (active_children)
+ {
+ cell->get_interpolated_dof_values(u3, dof_values);
+ cell->set_dof_values_by_interpolation(dof_values, u2);
+ }
+ }
+ }
+
+ // Apply hanging node constraints.
+ constraints.distribute(u2);
+ }
+
+} // end of namespace FETools
+
+
+
+/*-------------- Explicit Instantiations -------------------------------*/
+#include "fe_tools_interpolate.inst"
+
+
+/*---------------------------- fe_tools.cc ---------------------------*/
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; Vector : SERIAL_VECTORS)
+ {
+ namespace FETools
+ \{
+#if deal_II_dimension <= deal_II_space_dimension
+ template
+ void interpolate<deal_II_dimension,deal_II_space_dimension>
+ (const DoFHandler<deal_II_dimension,deal_II_space_dimension> &, const Vector &,
+ const DoFHandler<deal_II_dimension,deal_II_space_dimension> &, Vector &);
+
+ template
+ void interpolate<deal_II_dimension,deal_II_space_dimension>
+ (const DoFHandler<deal_II_dimension,deal_II_space_dimension> &, const Vector &,
+ const DoFHandler<deal_II_dimension,deal_II_space_dimension> &, const ConstraintMatrix &,
+ Vector &);
+#endif
+ \}
+ }
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+ namespace FETools
+ \{
+#if deal_II_dimension == deal_II_space_dimension
+ template
+ void interpolate<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension> &, const Vector<double> &,
+ const hp::DoFHandler<deal_II_dimension> &, Vector<double> &);
+ template
+ void interpolate<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension> &, const Vector<double> &,
+ const hp::DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
+ Vector<double> &);
+ template
+ void interpolate<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension> &, const Vector<float> &,
+ const hp::DoFHandler<deal_II_dimension> &, Vector<float> &);
+ template
+ void interpolate<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension> &, const Vector<float> &,
+ const hp::DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
+ Vector<float> &);
+#endif
+ \}
+ }
+
+
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; VEC : SERIAL_VECTORS)
+ {
+ namespace FETools
+ \{
+#if deal_II_dimension == deal_II_space_dimension
+ template
+ void back_interpolate<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &, const VEC &,
+ const FiniteElement<deal_II_dimension> &, VEC &);
+ template
+ void back_interpolate<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
+ const VEC &,
+ const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
+ VEC &);
+ template
+ void interpolation_difference<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &, const VEC &,
+ const FiniteElement<deal_II_dimension> &, VEC &);
+ template
+ void interpolation_difference<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
+ const VEC &,
+ const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
+ VEC &);
+ template
+ void project_dg<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &, const VEC &,
+ const DoFHandler<deal_II_dimension> &, VEC &);
+ template
+ void extrapolate<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &, const VEC &,
+ const DoFHandler<deal_II_dimension> &, VEC &);
+ template
+ void extrapolate<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &, const VEC &,
+ const DoFHandler<deal_II_dimension> &, const ConstraintMatrix &,
+ VEC &);
+#endif
+ \}
+ }
const unsigned int dim = 2;
std::vector<Point<dim> > line_points (2);
- // loop over each of the lines,
- // and if it is at the
- // boundary, then first get the
- // boundary description and
- // second compute the points on
- // it. if not at the boundary,
- // get the respective points
- // from another function
+ // loop over each of the lines, and if it is at the boundary, then first get
+ // the boundary description and second compute the points on it. if not at
+ // the boundary, get the respective points from another function
for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
{
const Triangulation<dim>::line_iterator line = cell->line(line_no);
if (line->at_boundary())
{
- // first get the normal
- // vectors at the two
- // vertices of this line
- // from the boundary
- // description
+ // first get the normal vectors at the two vertices of this line
+ // from the boundary description
const Boundary<dim> &boundary
= line->get_triangulation().get_boundary(line->boundary_indicator());
Boundary<dim>::FaceVertexNormals face_vertex_normals;
boundary.get_normals_at_vertices (line, face_vertex_normals);
- // then transform them into
- // interpolation points for
- // a cubic polynomial
+ // then transform them into interpolation points for a cubic
+ // polynomial
//
- // for this, note that if
- // we describe the boundary
- // curve as a polynomial in
- // tangential coordinate
- // @p{t=0..1} (along the
- // line) and @p{s} in
- // normal direction, then
- // the cubic mapping is
- // such that @p{s = a*t**3
- // + b*t**2 + c*t + d}, and
- // we want to determine the
- // interpolation points at
- // @p{t=1/3} and
- // @p{t=2/3}. Since at
- // @p{t=0,1} we want a
- // vertex which is actually
- // at the boundary, we know
- // that @p{d=0} and
- // @p{a=-b-c}. As
- // side-conditions, we want
- // that the derivatives at
- // @p{t=0} and @p{t=1},
- // i.e. at the vertices
- // match those returned by
- // the boundary. We then
- // have that
- // @p{s(1/3)=1/27(2b+8c)}
- // and
- // @p{s(2/3)=4/27b+10/27c}.
+ // for this, note that if we describe the boundary curve as a
+ // polynomial in tangential coordinate @p{t=0..1} (along the line)
+ // and @p{s} in normal direction, then the cubic mapping is such
+ // that @p{s = a*t**3 + b*t**2 + c*t + d}, and we want to determine
+ // the interpolation points at @p{t=0.276} and @p{t=0.724}
+ // (Gauss-Lobatto points). Since at @p{t=0,1} we want a vertex which
+ // is actually at the boundary, we know that @p{d=0} and @p{a=-b-c},
+ // which gives @p{s(0.276)} and @{s(0.726)} in terms of @p{b,c}. As
+ // side-conditions, we want that the derivatives at @p{t=0} and
+ // @p{t=1}, i.e. at the vertices match those returned by the
+ // boundary.
//
- // The task is then first
- // to determine the
- // coefficients from the
- // tangentials. for that,
- // first rotate the
- // tangents of @p{s(t)}
- // into the global
- // coordinate system. they
- // are @p{A (1,c)} and @p{A
- // (1,-b-2c)} with @p{A} the
- // rotation matrix, since
- // the tangentials in the
- // coordinate system
- // relative to the line are
- // @p{(1,c)} and @p{(1,-b-2c)}
- // at the two vertices,
- // respectively. We then
- // have to make sure by
- // matching @p{b,c} that
- // these tangentials are
- // orthogonal to the normals
- // returned by the boundary
- // object
+ // The task is then first to determine the coefficients from the
+ // tangentials. for that, first rotate the tangents of @p{s(t)} into
+ // the global coordinate system. they are @p{A (1,c)} and @p{A
+ // (1,-b-2c)} with @p{A} the rotation matrix, since the tangentials
+ // in the coordinate system relative to the line are @p{(1,c)} and
+ // @p{(1,-b-2c)} at the two vertices, respectively. We then have to
+ // make sure by matching @p{b,c} that these tangentials are
+ // orthogonal to the normals returned by the boundary object
const Tensor<1,2> coordinate_vector = line->vertex(1) - line->vertex(0);
const double h = std::sqrt(coordinate_vector * coordinate_vector);
Tensor<1,2> coordinate_axis = coordinate_vector;
-face_vertex_normals[1][0] * std::sin(alpha)))
-2*c;
+ QGaussLobatto<1> quad_points(4);
+ const double t1 = quad_points.point(1)[0];
+ const double t2 = quad_points.point(2)[0];
+ const double s_t1 = (((-b-c)*t1+b)*t1+c)*t1;
+ const double s_t2 = (((-b-c)*t2+b)*t2+c)*t2;
- // next evaluate the so
- // determined cubic
- // polynomial at the points
- // 1/3 and 2/3, first in
- // unit coordinates
- const Point<2> new_unit_points[2] = { Point<2>(1./3., 1./27.*(2*b+8*c)),
- Point<2>(2./3., 4./27.*b+10./27.*c)
+ // next evaluate the so determined cubic polynomial at the points
+ // 1/3 and 2/3, first in unit coordinates
+ const Point<2> new_unit_points[2] = { Point<2>(t1, s_t1),
+ Point<2>(t2, s_t2)
};
- // then transform these
- // points to real
- // coordinates by rotating,
+ // then transform these points to real coordinates by rotating,
// scaling and shifting
for (unsigned int i=0; i<2; ++i)
{
|| (dim != spacedim)),
feq(degree)
{
- // Construct the tensor product
- // polynomials used as shape
- // functions for the Qp mapping of
- // cells at the boundary.
- std::vector<Polynomials::LagrangeEquidistant> v;
- for (unsigned int i=0; i<=degree; ++i)
- v.push_back(Polynomials::LagrangeEquidistant(degree,i));
-
- tensor_pols = new TensorProductPolynomials<dim> (v);
+ // Construct the tensor product polynomials used as shape functions for the
+ // Qp mapping of cells at the boundary.
+ const QGaussLobatto<1> points(degree+1);
+ tensor_pols = new TensorProductPolynomials<dim>
+ (Polynomials::generate_complete_Lagrange_basis(points.get_points()));
Assert (n_shape_functions==tensor_pols->n(),
ExcInternalError());
Assert(n_inner+n_outer==n_shape_functions, ExcInternalError());
}
-// Note that the CellSimilarity flag is
-// modifyable, since MappingQ can need to
-// recalculate data even when cells are
-// similar.
+// Note that the CellSimilarity flag is modifyable, since MappingQ can need to
+// recalculate data even when cells are similar.
template<int dim, int spacedim>
void
MappingQ<dim,spacedim>::fill_fe_values (
std::vector<Point<spacedim> > &normal_vectors,
CellSimilarity::Similarity &cell_similarity) const
{
- // convert data object to internal
- // data for this class. fails with
- // an exception if that is not
- // possible
+ // convert data object to internal data for this class. fails with an
+ // exception if that is not possible
Assert (dynamic_cast<InternalData *> (&mapping_data) != 0, ExcInternalError());
InternalData &data = static_cast<InternalData &> (mapping_data);
- // check whether this cell needs
- // the full mapping or can be
- // treated by a reduced Q1 mapping,
- // e.g. if the cell is in the
- // interior of the domain
+ // check whether this cell needs the full mapping or can be treated by a
+ // reduced Q1 mapping, e.g. if the cell is in the interior of the domain
data.use_mapping_q1_on_current_cell = !(use_mapping_q_on_all_cells
|| cell->has_boundary_lines());
- // depending on this result, use this or
- // the other data object for the
- // mapping. furthermore, we need to
- // ensure that the flag indicating
- // whether we can use some similarity has
- // to be modified - for a general
- // MappingQ, the data needs to be
- // recomputed anyway since then the
- // mapping changes the data. this needs
- // to be known also for later operations,
- // so modify the variable here. this also
- // affects the calculation of the next
- // cell -- if we use Q1 data on the next
- // cell, the data will still be invalid.
+ // depending on this result, use this or the other data object for the
+ // mapping. furthermore, we need to ensure that the flag indicating whether
+ // we can use some similarity has to be modified - for a general MappingQ,
+ // the data needs to be recomputed anyway since then the mapping changes the
+ // data. this needs to be known also for later operations, so modify the
+ // variable here. this also affects the calculation of the next cell -- if
+ // we use Q1 data on the next cell, the data will still be invalid.
typename MappingQ1<dim,spacedim>::InternalData *p_data=0;
if (data.use_mapping_q1_on_current_cell)
p_data=&data.mapping_q1_data;
std::vector<Tensor<1,spacedim> > &exterior_forms,
std::vector<Point<spacedim> > &normal_vectors) const
{
- // convert data object to internal
- // data for this class. fails with
- // an exception if that is not
- // possible
+ // convert data object to internal data for this class. fails with an
+ // exception if that is not possible
Assert (dynamic_cast<InternalData *> (&mapping_data) != 0,
ExcInternalError());
InternalData &data = static_cast<InternalData &> (mapping_data);
- // check whether this cell needs
- // the full mapping or can be
- // treated by a reduced Q1 mapping,
- // e.g. if the cell is entirely in
- // the interior of the domain. note
- // that it is not sufficient to ask
- // whether the present _face_ is in
- // the interior, as the mapping on
- // the face depends on the mapping
- // of the cell, which in turn
- // depends on the fact whether
- // _any_ of the faces of this cell
- // is at the boundary, not only the
- // present face
+ // check whether this cell needs the full mapping or can be treated by a
+ // reduced Q1 mapping, e.g. if the cell is entirely in the interior of the
+ // domain. note that it is not sufficient to ask whether the present _face_
+ // is in the interior, as the mapping on the face depends on the mapping of
+ // the cell, which in turn depends on the fact whether _any_ of the faces of
+ // this cell is at the boundary, not only the present face
data.use_mapping_q1_on_current_cell=!(use_mapping_q_on_all_cells
|| cell->has_boundary_lines());
- // depending on this result, use
- // this or the other data object
- // for the mapping
+ // depending on this result, use this or the other data object for the
+ // mapping
typename MappingQ1<dim,spacedim>::InternalData *p_data=0;
if (data.use_mapping_q1_on_current_cell)
p_data=&data.mapping_q1_data;
std::vector<Tensor<1,spacedim> > &exterior_forms,
std::vector<Point<spacedim> > &normal_vectors) const
{
- // convert data object to internal
- // data for this class. fails with
- // an exception if that is not
- // possible
+ // convert data object to internal data for this class. fails with an
+ // exception if that is not possible
Assert (dynamic_cast<InternalData *> (&mapping_data) != 0,
ExcInternalError());
InternalData &data = static_cast<InternalData &> (mapping_data);
- // check whether this cell needs
- // the full mapping or can be
- // treated by a reduced Q1 mapping,
- // e.g. if the cell is entirely in
- // the interior of the domain. note
- // that it is not sufficient to ask
- // whether the present _face_ is in
- // the interior, as the mapping on
- // the face depends on the mapping
- // of the cell, which in turn
- // depends on the fact whether
- // _any_ of the faces of this cell
- // is at the boundary, not only the
- // present face
+ // check whether this cell needs the full mapping or can be treated by a
+ // reduced Q1 mapping, e.g. if the cell is entirely in the interior of the
+ // domain. note that it is not sufficient to ask whether the present _face_
+ // is in the interior, as the mapping on the face depends on the mapping of
+ // the cell, which in turn depends on the fact whether _any_ of the faces of
+ // this cell is at the boundary, not only the present face
data.use_mapping_q1_on_current_cell=!(use_mapping_q_on_all_cells
|| cell->has_boundary_lines());
- // depending on this result, use
- // this or the other data object
- // for the mapping
+ // depending on this result, use this or the other data object for the
+ // mapping
typename MappingQ1<dim,spacedim>::InternalData *p_data=0;
if (data.use_mapping_q1_on_current_cell)
p_data=&data.mapping_q1_data;
const unsigned int n_inner_2d=(degree-1)*(degree-1);
const unsigned int n_outer_2d=4+4*(degree-1);
- // first check whether we have precomputed
- // the values for some polynomial degree;
- // the sizes of arrays is
- // n_inner_2d*n_outer_2d
+ // first check whether we have precomputed the values for some polynomial
+ // degree; the sizes of arrays is n_inner_2d*n_outer_2d
double const *loqv_ptr=0;
switch (degree)
{
- // for degree==1, we shouldn't have to
- // compute any support points, since
+ // for degree==1, we shouldn't have to compute any support points, since
// all of them are on the vertices
case 2:
{
- // (checked these values against the
- // output of compute_laplace_vector
- // again, and found they're indeed
- // right -- just in case someone
- // wonders where they come from --
- // WB)
+ // (checked these values against the output of compute_laplace_vector
+ // again, and found they're indeed right -- just in case someone wonders
+ // where they come from -- WB)
static const double loqv2[1*8]
= {1/16., 1/16., 1/16., 1/16., 3/16., 3/16., 3/16., 3/16.};
loqv_ptr=&loqv2[0];
break;
}
- case 3:
- {
- // (same as above)
- static const double loqv3[4*12]
- = {80/1053., 1/81., 1/81., 11/1053., 25/117., 44/351.,
- 7/117., 16/351., 25/117., 44/351., 7/117., 16/351.,
- 1/81., 80/1053., 11/1053., 1/81., 7/117., 16/351.,
- 25/117., 44/351., 44/351., 25/117., 16/351., 7/117.,
- 1/81., 11/1053., 80/1053., 1/81., 44/351., 25/117.,
- 16/351., 7/117., 7/117., 16/351., 25/117., 44/351.,
- 11/1053., 1/81., 1/81., 80/1053., 16/351., 7/117.,
- 44/351., 25/117., 16/351., 7/117., 44/351., 25/117.
- };
- Assert (sizeof(loqv3)/sizeof(loqv3[0]) ==
- n_inner_2d * n_outer_2d,
- ExcInternalError());
-
- loqv_ptr=&loqv3[0];
-
- break;
- }
-
-
- case 4:
- {
- static const double loqv4[9*16]
- = {0.07405921850311571, -0.001075744628905992,
- -0.001075744628906007, 0.001914292239071463,
- 0.2231273865431892, 0.1346851306015187,
- 0.03812914216116724, 0.02913160002633252,
- 0.02200737428129396, 0.01600835564431224,
- 0.2231273865431891, 0.1346851306015187,
- 0.03812914216116723, 0.02913160002633253,
- 0.02200737428129391, 0.01600835564431222,
-
- 0.00664803151334206, 0.006648031513342719,
- 0.002873452861657458, 0.002873452861657626,
- 0.07903572682584378, 0.05969238281250031,
- 0.03619864817415824, 0.07903572682584187,
- 0.0596923828124999, 0.03619864817415815,
- 0.1527716818820237, 0.2348152760709273,
- 0.152771681882024, 0.02496269311797778,
- 0.04081948955407129, 0.02496269311797789,
-
- -0.001075744628906923, 0.07405921850311589,
- 0.001914292239071339, -0.001075744628905884,
- 0.02913160002633509, 0.02200737428129395,
- 0.01600835564431229, 0.2231273865431878,
- 0.1346851306015183, 0.0381291421611672,
- 0.03812914216116729, 0.1346851306015185,
- 0.2231273865431898, 0.01600835564431217,
- 0.02200737428129394, 0.02913160002633262,
-
- 0.006648031513342073, 0.002873452861657473,
- 0.006648031513342726, 0.002873452861657636,
- 0.1527716818820238, 0.2348152760709273,
- 0.152771681882024, 0.02496269311797779,
- 0.04081948955407131, 0.0249626931179779,
- 0.07903572682584376, 0.05969238281250026,
- 0.03619864817415824, 0.07903572682584187,
- 0.0596923828124998, 0.0361986481741581,
-
- 0.01106770833333302, 0.01106770833333336,
- 0.01106770833333337, 0.01106770833333374,
- 0.06770833333333424, 0.1035156250000011,
- 0.0677083333333344, 0.06770833333333376,
- 0.103515624999999, 0.06770833333333399,
- 0.06770833333333422, 0.1035156250000009,
- 0.06770833333333436, 0.0677083333333337,
- 0.1035156249999988, 0.0677083333333339,
-
- 0.002873452861657185, 0.006648031513342362,
- 0.002873452861657334, 0.006648031513343038,
- 0.02496269311797779, 0.04081948955407401,
- 0.02496269311797788, 0.1527716818820234,
- 0.234815276070926, 0.1527716818820237,
- 0.03619864817415819, 0.05969238281250028,
- 0.07903572682584407, 0.03619864817415804,
- 0.05969238281249986, 0.0790357268258422,
-
- -0.001075744628906913, 0.00191429223907134,
- 0.07405921850311592, -0.001075744628905865,
- 0.03812914216116729, 0.1346851306015185,
- 0.2231273865431899, 0.01600835564431217,
- 0.02200737428129396, 0.02913160002633264,
- 0.02913160002633509, 0.02200737428129391,
- 0.01600835564431228, 0.2231273865431878,
- 0.1346851306015183, 0.03812914216116718,
-
- 0.002873452861657176, 0.002873452861657321,
- 0.006648031513342374, 0.006648031513343037,
- 0.03619864817415817, 0.05969238281250032,
- 0.07903572682584409, 0.03619864817415805,
- 0.05969238281249992, 0.07903572682584221,
- 0.02496269311797776, 0.04081948955407392,
- 0.02496269311797785, 0.1527716818820233,
- 0.2348152760709258, 0.1527716818820236,
-
- 0.001914292239071237, -0.001075744628906803,
- -0.001075744628906778, 0.07405921850311617,
- 0.01600835564431228, 0.02200737428129401,
- 0.02913160002633524, 0.03812914216116726,
- 0.1346851306015182, 0.2231273865431886,
- 0.01600835564431228, 0.02200737428129397,
- 0.02913160002633523, 0.03812914216116726,
- 0.1346851306015181, 0.2231273865431886,
- };
-
- Assert (sizeof(loqv4)/sizeof(loqv4[0]) ==
- n_inner_2d * n_outer_2d,
- ExcInternalError());
-
- loqv_ptr=&loqv4[0];
-
- break;
- }
-
- // no other cases implemented,
- // so simply fall through
+ // no other cases implemented, so simply fall through
default:
break;
}
if (loqv_ptr!=0)
{
- // precomputed. copy values to
- // the loqvs array
+ // precomputed. copy values to the loqvs array
loqvs.reinit(n_inner_2d, n_outer_2d);
for (unsigned int unit_point=0; unit_point<n_inner_2d; ++unit_point)
for (unsigned int k=0; k<n_outer_2d; ++k)
else
{
// not precomputed, then do so now
- if (dim==2)
+ if (dim == 2)
compute_laplace_vector(loqvs);
- else
- // computing the Laplace vector for
- // faces is not supported in 3d at
- // present. presumably, doing so
- // would not be so hard: we would
- // only have to call the function in
- // 2d, i.e. the quad(=face) values in
- // 3d are equal to the quad(=cell)
- // values in 2d. however, that would
- // require us to link in the 2d
- // library, which is kind of awkward
- // (note that compute_laplace_vector
- // really makes use of a lot of 2d
- // stuff, such as FEValues etc). an
- // alternative would be to precompute
- // the values of this array for a
- // couple of higher mapping orders,
- // pin down their values and insert
- // them into the array above.
- Assert (false, ExcNotImplemented());
+ else if (dim == 3)
+ {
+ MappingQ<2,2> mapping_2d(this->degree);
+ loqvs = mapping_2d.laplace_on_quad_vector;
+ }
}
- // the sum of weights of the points
- // at the outer rim should be
- // one. check this
+ // the sum of weights of the points at the outer rim should be one. check
+ // this
for (unsigned int unit_point=0; unit_point<loqvs.n_rows(); ++unit_point)
Assert(std::fabs(std::accumulate(loqvs[unit_point].begin(),
- loqvs[unit_point].end(),0.)-1)<1e-12*this->degree*this->degree,
+ loqvs[unit_point].end(),0.)-1)<1e-13*this->degree,
ExcInternalError());
}
{
Assert(degree>1, ExcInternalError());
- // first check whether we have
- // precomputed the values for some
- // polynomial degree
+ // first check whether we have precomputed the values for some polynomial
+ // degree
double const *lohv_ptr=0;
if (degree==2)
{
if (lohv_ptr!=0)
{
- // precomputed. copy values to
- // the lohvs array
+ // precomputed. copy values to the lohvs array
lohvs.reinit(n_inner, n_outer);
for (unsigned int unit_point=0; unit_point<n_inner; ++unit_point)
for (unsigned int k=0; k<n_outer; ++k)
// not precomputed, then do so now
compute_laplace_vector(lohvs);
- // the sum of weights of the points
- // at the outer rim should be
- // one. check this
+ // the sum of weights of the points at the outer rim should be one. check
+ // this
for (unsigned int unit_point=0; unit_point<n_inner; ++unit_point)
Assert(std::fabs(std::accumulate(lohvs[unit_point].begin(),
- lohvs[unit_point].end(),0.) - 1)<1e-13,
+ lohvs[unit_point].end(),0.) - 1)<1e-12*this->degree*this->degree,
ExcInternalError());
}
Assert(lvs.n_rows()==0, ExcInternalError());
Assert(dim==2 || dim==3, ExcNotImplemented());
- // for degree==1, we shouldn't have to
- // compute any support points, since all of
- // them are on the vertices
+ // for degree==1, we shouldn't have to compute any support points, since all
+ // of them are on the vertices
Assert(degree>1, ExcInternalError());
- // compute the shape
- // gradients at the quadrature
- // points on the unit cell
+ // compute the shape gradients at the quadrature points on the unit cell
const QGauss<dim> quadrature(degree+1);
const unsigned int n_q_points=quadrature.size();
quadrature_data.shape_derivatives.resize(n_shape_functions * n_q_points);
this->compute_shapes(quadrature.get_points(), quadrature_data);
- // Compute the stiffness matrix of
- // the inner dofs
- FullMatrix<double> S(n_inner);
+ // Compute the stiffness matrix of the inner dofs
+ FullMatrix<long double> S(n_inner);
for (unsigned int point=0; point<n_q_points; ++point)
for (unsigned int i=0; i<n_inner; ++i)
for (unsigned int j=0; j<n_inner; ++j)
- S(i,j) += contract(quadrature_data.derivative(point, n_outer+i),
- quadrature_data.derivative(point, n_outer+j))
- * quadrature.weight(point);
+ {
+ long double res = 0.;
+ for (unsigned int l=0; l<dim; ++l)
+ res += (long double)quadrature_data.derivative(point, n_outer+i)[l] *
+ (long double)quadrature_data.derivative(point, n_outer+j)[l];
- // Compute the components of T to be the
- // product of gradients of inner and
+ S(i,j) += res * (long double)quadrature.weight(point);
+ }
+
+ // Compute the components of T to be the product of gradients of inner and
// outer shape functions.
- FullMatrix<double> T(n_inner, n_outer);
+ FullMatrix<long double> T(n_inner, n_outer);
for (unsigned int point=0; point<n_q_points; ++point)
for (unsigned int i=0; i<n_inner; ++i)
for (unsigned int k=0; k<n_outer; ++k)
- T(i,k) += contract(quadrature_data.derivative(point, n_outer+i),
- quadrature_data.derivative(point, k))
- *quadrature.weight(point);
+ {
+ long double res = 0.;
+ for (unsigned int l=0; l<dim; ++l)
+ res += (long double)quadrature_data.derivative(point, n_outer+i)[l] *
+ (long double)quadrature_data.derivative(point, k)[l];
+
+ T(i,k) += res *(long double)quadrature.weight(point);
+ }
- FullMatrix<double> S_1(n_inner);
+ FullMatrix<long double> S_1(n_inner);
S_1.invert(S);
- FullMatrix<double> S_1_T(n_inner, n_outer);
+ FullMatrix<long double> S_1_T(n_inner, n_outer);
// S:=S_1*T
S_1.mmult(S_1_T,T);
- // Resize and initialize the
- // lvs
+ // Resize and initialize the lvs
lvs.reinit (n_inner, n_outer);
for (unsigned int i=0; i<n_inner; ++i)
for (unsigned int k=0; k<n_outer; ++k)
MappingQ<dim,spacedim>::apply_laplace_vector(const Table<2,double> &lvs,
std::vector<Point<spacedim> > &a) const
{
- // check whether the data we need
- // is really available. if you fail
- // here and if
- // lvs==laplace_on_quad_vector in
- // the calling function, then we
- // didn't compute the quad laplace
- // vector. this is mentioned in the
- // constructor of this class,
- // although I don't understand the
- // reason for not aborting there
+ // check whether the data we need is really available. if you fail here and
+ // if lvs==laplace_on_quad_vector in the calling function, then we didn't
+ // compute the quad laplace vector. this is mentioned in the constructor of
+ // this class, although I don't understand the reason for not aborting there
// any more [WB]
Assert(lvs.n_rows()!=0, ExcLaplaceVectorNotSet(degree));
Assert(a.size()==n_outer_apply,
ExcDimensionMismatch(a.size(), n_outer_apply));
- // compute each inner point as
- // linear combination of the outer
- // points. the weights are given by
- // the lvs entries, the outer
- // points are the first (existing)
- // elements of a
+ // compute each inner point as linear combination of the outer points. the
+ // weights are given by the lvs entries, the outer points are the first
+ // (existing) elements of a
for (unsigned int unit_point=0; unit_point<n_inner_apply; ++unit_point)
{
Assert(lvs.n_cols()==n_outer_apply, ExcInternalError());
const typename Triangulation<dim,spacedim>::cell_iterator &cell,
std::vector<Point<spacedim> > &a) const
{
- // if this is a cell for which we
- // want to compute the full
- // mapping, then get them from the
- // following function
+ // if this is a cell for which we want to compute the full mapping, then get
+ // them from the following function
if (use_mapping_q_on_all_cells || cell->has_boundary_lines())
compute_support_points_laplace(cell, a);
else
- // otherwise: use a Q1 mapping
- // for which the mapping shape
- // function support points are
- // simply the vertices of the
- // cell
+ // otherwise: use a Q1 mapping for which the mapping shape function
+ // support points are simply the vertices of the cell
{
a.resize(GeometryInfo<dim>::vertices_per_cell);
MappingQ<dim,spacedim>::compute_support_points_laplace(const typename Triangulation<dim,spacedim>::cell_iterator &cell,
std::vector<Point<spacedim> > &a) const
{
- // in any case, we need the
- // vertices first
+ // in any case, we need the vertices first
a.resize(GeometryInfo<dim>::vertices_per_cell);
for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
a[i] = cell->vertex(i);
add_line_support_points(cell, a);
break;
case 2:
- // in 2d, add the
- // points on the four
- // bounding lines to
- // the exterior (outer)
- // points
+ // in 2d, add the points on the four bounding lines to the exterior
+ // (outer) points
add_line_support_points (cell, a);
if (dim != spacedim)
add_quad_support_points(cell, a);
case 3:
{
- // in 3d also add the
- // points located on
- // the boundary faces
+ // in 3d also add the points located on the boundary faces
add_line_support_points (cell, a);
add_quad_support_points (cell, a);
apply_laplace_vector (laplace_on_hex_vector, a);
MappingQ<1>::add_line_support_points (const Triangulation<1>::cell_iterator &,
std::vector<Point<1> > &) const
{
- // there are no points on bounding
- // lines which are to be added
+ // there are no points on bounding lines which are to be added
const unsigned int dim=1;
Assert (dim > 1, ExcImpossibleInDim(dim));
}
{
const unsigned int dim = 1;
const unsigned int spacedim = 2;
- // Ask for the mid point, if that's
- // the only thing we need.
+ // Ask for the mid point, if that's the only thing we need.
if (degree==2)
{
const Boundary<dim,spacedim> *const boundary
a.push_back(boundary->get_new_point_on_line(cell));
}
else
- // otherwise call the more
- // complicated functions and ask
- // for inner points from the
- // boundary description
+ // otherwise call the more complicated functions and ask for inner points
+ // from the boundary description
{
std::vector<Point<spacedim> > line_points (degree-1);
{
const unsigned int dim = 1;
const unsigned int spacedim = 3;
- // Ask for the mid point, if that's
- // the only thing we need.
+ // Ask for the mid point, if that's the only thing we need.
if (degree==2)
{
const Boundary<dim,spacedim> *const boundary
a.push_back(boundary->get_new_point_on_line(cell));
}
else
- // otherwise call the more
- // complicated functions and ask
- // for inner points from the
- // boundary description
+ // otherwise call the more complicated functions and ask for inner points
+ // from the boundary description
{
std::vector<Point<spacedim> > line_points (degree-1);
std::vector<Point<spacedim> > &a) const
{
static const StraightBoundary<dim,spacedim> straight_boundary;
- // if we only need the midpoint,
- // then ask for it.
+ // if we only need the midpoint, then ask for it.
if (degree==2)
{
for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
};
}
else
- // otherwise call the more
- // complicated functions and ask
- // for inner points from the
- // boundary description
+ // otherwise call the more complicated functions and ask for inner points
+ // from the boundary description
{
std::vector<Point<spacedim> > line_points (degree-1);
- // loop over each of the lines,
- // and if it is at the
- // boundary, then first get the
- // boundary description and
- // second compute the points on
- // it
+ // loop over each of the lines, and if it is at the boundary, then first
+ // get the boundary description and second compute the points on it
for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
{
const typename Triangulation<dim,spacedim>::line_iterator line = cell->line(line_no);
boundary->get_intermediate_points_on_line (line, line_points);
if (dim==3)
{
- // in 3D, lines might be in wrong
- // orientation. if so, reverse
+ // in 3D, lines might be in wrong orientation. if so, reverse
// the vector
if (cell->line_orientation(line_no))
a.insert (a.end(), line_points.begin(), line_points.end());
a.insert (a.end(), line_points.rbegin(), line_points.rend());
}
else
- // in 2D, lines always have the
- // correct orientation. simply
- // append all points
+ // in 2D, lines always have the correct orientation. simply append
+ // all points
a.insert (a.end(), line_points.begin(), line_points.end());
}
vertices_per_cell = GeometryInfo<3>::vertices_per_cell;
static const StraightBoundary<3> straight_boundary;
- // used if face quad at boundary or
- // entirely in the interior of the
- // domain
+ // used if face quad at boundary or entirely in the interior of the domain
std::vector<Point<3> > quad_points ((degree-1)*(degree-1));
- // used if only one line of face
- // quad is at boundary
+ // used if only one line of face quad is at boundary
std::vector<Point<3> > b(4*degree);
- // loop over all faces and collect
- // points on them
+ // loop over all faces and collect points on them
for (unsigned int face_no=0; face_no<faces_per_cell; ++face_no)
{
const Triangulation<3>::face_iterator face = cell->face(face_no);
- // select the correct mappings
- // for the present face
+ // select the correct mappings for the present face
const bool face_orientation = cell->face_orientation(face_no),
face_flip = cell->face_flip (face_no),
face_rotation = cell->face_rotation (face_no);
face_rotation)),
ExcInternalError());
- // indices of the lines that
- // bound a face are given by
- // GeometryInfo<3>::
+ // indices of the lines that bound a face are given by GeometryInfo<3>::
// face_to_cell_lines
for (unsigned int i=0; i<lines_per_face; ++i)
Assert(face->line(i)==cell->line(GeometryInfo<3>::face_to_cell_lines(
ExcInternalError());
#endif
- // if face at boundary, then
- // ask boundary object to
- // return intermediate points
- // on it
+ // if face at boundary, then ask boundary object to return intermediate
+ // points on it
if (face->at_boundary())
{
face->get_triangulation().get_boundary(face->boundary_indicator())
.get_intermediate_points_on_quad (face, quad_points);
- // in 3D, the orientation, flip and
- // rotation of the face might not
- // match what we expect here, namely
- // the standard orientation. thus
- // reorder points accordingly. since
- // a Mapping uses the same shape
- // function as an FEQ, we can ask a
- // FEQ to do the reordering for us.
+ // in 3D, the orientation, flip and rotation of the face might not
+ // match what we expect here, namely the standard orientation. thus
+ // reorder points accordingly. since a Mapping uses the same shape
+ // function as an FEQ, we can ask a FEQ to do the reordering for us.
for (unsigned int i=0; i<quad_points.size(); ++i)
a.push_back(quad_points[feq.adjust_quad_dof_index_for_face_orientation(i,
face_orientation,
}
else
{
- // face is not at boundary,
- // but maybe some of its
- // lines are. count them
+ // face is not at boundary, but maybe some of its lines are. count
+ // them
unsigned int lines_at_boundary=0;
for (unsigned int i=0; i<lines_per_face; ++i)
if (face->line(i)->at_boundary())
Assert(lines_at_boundary<=lines_per_face, ExcInternalError());
- // if at least one of the
- // lines bounding this quad
- // is at the boundary, then
- // collect points
- // separately
+ // if at least one of the lines bounding this quad is at the
+ // boundary, then collect points separately
if (lines_at_boundary>0)
{
- // call of function
- // apply_laplace_vector
- // increases size of b
- // about 1. There
- // resize b for the
- // case the mentioned
- // function was already
- // called.
+ // call of function apply_laplace_vector increases size of b
+ // about 1. There resize b for the case the mentioned function
+ // was already called.
b.resize(4*degree);
- // b is of size
- // 4*degree, make sure
- // that this is the
- // right size
+ // b is of size 4*degree, make sure that this is the right size
Assert(b.size()==vertices_per_face+lines_per_face*(degree-1),
ExcDimensionMismatch(b.size(),
vertices_per_face+lines_per_face*(degree-1)));
- // sort the points into b. We
- // used access from the cell (not
- // from the face) to fill b, so
- // we can assume a standard face
- // orientation. Doing so, the
- // calculated points will be in
+ // sort the points into b. We used access from the cell (not
+ // from the face) to fill b, so we can assume a standard face
+ // orientation. Doing so, the calculated points will be in
// standard orientation as well.
for (unsigned int i=0; i<vertices_per_face; ++i)
b[i]=a[GeometryInfo<3>::face_to_cell_vertices(face_no, i)];
a[vertices_per_cell + GeometryInfo<3>::face_to_cell_lines(
face_no, i)*(degree-1)+j];
- // Now b includes the support
- // points on the quad and we can
+ // Now b includes the support points on the quad and we can
// apply the laplace vector
apply_laplace_vector(laplace_on_quad_vector, b);
Assert(b.size()==4*degree+(degree-1)*(degree-1),
}
else
{
- // face is entirely in
- // the interior. get
- // intermediate points
- // from a straight
- // boundary object
+ // face is entirely in the interior. get intermediate points
+ // from a straight boundary object
straight_boundary.get_intermediate_points_on_quad (face, quad_points);
- // in 3D, the orientation, flip
- // and rotation of the face might
- // not match what we expect here,
- // namely the standard
- // orientation. thus reorder
- // points accordingly. since a
- // Mapping uses the same shape
- // function as an FEQ, we can ask
- // a FEQ to do the reordering for
- // us.
+ // in 3D, the orientation, flip and rotation of the face might
+ // not match what we expect here, namely the standard
+ // orientation. thus reorder points accordingly. since a Mapping
+ // uses the same shape function as an FEQ, we can ask a FEQ to
+ // do the reordering for us.
for (unsigned int i=0; i<quad_points.size(); ++i)
a.push_back(quad_points[feq.adjust_quad_dof_index_for_face_orientation(i,
face_orientation,
const MappingType mapping_type) const
{
AssertDimension (input.size(), output.size());
- // The data object may be just a
- // MappingQ1::InternalData, so we
- // have to test for this first.
+ // The data object may be just a MappingQ1::InternalData, so we have to test
+ // for this first.
const typename MappingQ1<dim,spacedim>::InternalData *q1_data =
dynamic_cast<const typename MappingQ1<dim,spacedim>::InternalData *> (&mapping_data);
Assert(q1_data!=0, ExcInternalError());
- // If it is a genuine
- // MappingQ::InternalData, we have
- // to test further
+ // If it is a genuine MappingQ::InternalData, we have to test further
if (!q1_data->is_mapping_q1_data)
{
Assert (dynamic_cast<const InternalData *>(&mapping_data) != 0,
ExcInternalError());
const InternalData &data = static_cast<const InternalData &>(mapping_data);
- // If we only use the
- // Q1-portion, we have to
- // extract that data object
+ // If we only use the Q1-portion, we have to extract that data object
if (data.use_mapping_q1_on_current_cell)
q1_data = &data.mapping_q1_data;
}
- // Now, q1_data should have the
- // right tensors in it and we call
- // the base classes transform
- // function
+ // Now, q1_data should have the right tensors in it and we call the base
+ // classes transform function
MappingQ1<dim,spacedim>::transform(input, output, *q1_data, mapping_type);
}
const MappingType mapping_type) const
{
AssertDimension (input.size(), output.size());
- // The data object may be just a
- // MappingQ1::InternalData, so we
- // have to test for this first.
+ // The data object may be just a MappingQ1::InternalData, so we have to test
+ // for this first.
const typename MappingQ1<dim,spacedim>::InternalData *q1_data =
dynamic_cast<const typename MappingQ1<dim,spacedim>::InternalData *> (&mapping_data);
Assert(q1_data!=0, ExcInternalError());
- // If it is a genuine
- // MappingQ::InternalData, we have
- // to test further
+ // If it is a genuine MappingQ::InternalData, we have to test further
if (!q1_data->is_mapping_q1_data)
{
Assert (dynamic_cast<const InternalData *>(&mapping_data) != 0,
ExcInternalError());
const InternalData &data = static_cast<const InternalData &>(mapping_data);
- // If we only use the
- // Q1-portion, we have to
- // extract that data object
+ // If we only use the Q1-portion, we have to extract that data object
if (data.use_mapping_q1_on_current_cell)
q1_data = &data.mapping_q1_data;
}
- // Now, q1_data should have the
- // right tensors in it and we call
- // the base classes transform
- // function
+ // Now, q1_data should have the right tensors in it and we call the base
+ // classes transform function
MappingQ1<dim,spacedim>::transform(input, output, *q1_data, mapping_type);
}
const MappingType mapping_type) const
{
AssertDimension (input.size(), output.size());
- // The data object may be just a
- // MappingQ1::InternalData, so we
- // have to test for this first.
+ // The data object may be just a MappingQ1::InternalData, so we have to test
+ // for this first.
const typename MappingQ1<dim,spacedim>::InternalData *q1_data =
dynamic_cast<const typename MappingQ1<dim,spacedim>::InternalData *> (&mapping_data);
Assert(q1_data!=0, ExcInternalError());
- // If it is a genuine
- // MappingQ::InternalData, we have
- // to test further
+ // If it is a genuine MappingQ::InternalData, we have to test further
if (!q1_data->is_mapping_q1_data)
{
Assert (dynamic_cast<const InternalData *>(&mapping_data) != 0,
ExcInternalError());
const InternalData &data = static_cast<const InternalData &>(mapping_data);
- // If we only use the
- // Q1-portion, we have to
- // extract that data object
+ // If we only use the Q1-portion, we have to extract that data object
if (data.use_mapping_q1_on_current_cell)
q1_data = &data.mapping_q1_data;
}
- // Now, q1_data should have the
- // right tensors in it and we call
- // the base classes transform
- // function
+ // Now, q1_data should have the right tensors in it and we call the base
+ // classes transform function
MappingQ1<dim,spacedim>::transform(input, output, *q1_data, mapping_type);
}
transform_unit_to_real_cell (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
const Point<dim> &p) const
{
- // Use the get_data function to
- // create an InternalData with data
- // vectors of the right size and
- // transformation shape values
- // already computed at point p.
+ // Use the get_data function to create an InternalData with data vectors of
+ // the right size and transformation shape values already computed at point
+ // p.
const Quadrature<dim> point_quadrature(p);
std::auto_ptr<InternalData>
mdata (dynamic_cast<InternalData *> (
&*mdata);
compute_mapping_support_points(cell, p_data->mapping_support_points);
- // If this should be Q1, ignore all
- // other support points.
+ // If this should be Q1, ignore all other support points.
if (p_data->shape_values.size()<p_data->mapping_support_points.size())
p_data->mapping_support_points.resize
(GeometryInfo<dim>::vertices_per_cell);
transform_real_to_unit_cell (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
const Point<spacedim> &p) const
{
- // first a Newton iteration based
- // on a Q1 mapping to get a good
- // starting point, the idea being
- // that this is cheaper than trying
- // to start with the real mapping
- // and likely also more robust.
+ // first a Newton iteration based on a Q1 mapping to get a good starting
+ // point, the idea being that this is cheaper than trying to start with the
+ // real mapping and likely also more robust.
//
- // that said, this doesn't always
- // work: there are cases where the
- // point is outside the cell and
- // the inverse mapping doesn't
- // converge. in that case, use the
- // center point of the cell as a
- // starting point if we are to go
- // on using the full mapping, or
- // just propagate up the exception
- // if we had no intention of
- // continuing with the full mapping
+ // that said, this doesn't always work: there are cases where the point is
+ // outside the cell and the inverse mapping doesn't converge. in that case,
+ // use the center point of the cell as a starting point if we are to go on
+ // using the full mapping, or just propagate up the exception if we had no
+ // intention of continuing with the full mapping
Point<dim> initial_p_unit;
try
{
}
catch (const typename Mapping<dim,spacedim>::ExcTransformationFailed &)
{
- // mirror the conditions of the
- // code below to determine if
- // we need to use an arbitrary
- // starting point or if we just
- // need to rethrow the
+ // mirror the conditions of the code below to determine if we need to
+ // use an arbitrary starting point or if we just need to rethrow the
// exception
if (cell->has_boundary_lines()
||
throw;
}
- // then a Newton iteration based on the
- // full MappingQ if we need this. note that
- // for interior cells with dim==spacedim,
- // the mapping used is in fact a Q1
- // mapping, so there is nothing we need to
- // do unless the iteration above failed
+ // then a Newton iteration based on the full MappingQ if we need this. note
+ // that for interior cells with dim==spacedim, the mapping used is in fact a
+ // Q1 mapping, so there is nothing we need to do unless the iteration above
+ // failed
if (cell->has_boundary_lines()
||
use_mapping_q_on_all_cells
||
(dim!=spacedim) )
{
- // use the full mapping. in case the
- // function above should have given us
- // something back that lies outside the
- // unit cell (that might happen because
- // we may have given a point 'p' that
- // lies inside the cell with the higher
- // order mapping, but outside the
- // Q1-mapped reference cell), then
- // project it back into the reference
- // cell in hopes that this gives a
- // better starting point to the
- // following iteration
+ // use the full mapping. in case the function above should have given us
+ // something back that lies outside the unit cell (that might happen
+ // because we may have given a point 'p' that lies inside the cell with
+ // the higher order mapping, but outside the Q1-mapped reference cell),
+ // then project it back into the reference cell in hopes that this gives
+ // a better starting point to the following iteration
initial_p_unit = GeometryInfo<dim>::project_to_unit_cell(initial_p_unit);
const Quadrature<dim> point_quadrature(initial_p_unit);
compute_mapping_support_points (cell, mdata->mapping_support_points);
- // If this is a q1 mapping,
- // then only use the support
- // points on the vertices.
+ // If this is a q1 mapping, then only use the support points on the
+ // vertices.
if (mdata->shape_values.size() < mdata->mapping_support_points.size())
mdata->mapping_support_points.resize(GeometryInfo<dim>::vertices_per_cell);
-
return this->transform_real_to_unit_cell_internal(cell, p, initial_p_unit, *mdata);
}
else
:
Quadrature<dim>(Utilities::fixed_power<dim>(map_degree+1))
{
- // first we determine the support points
- // on the unit cell in lexicographic order.
- // for this purpose we can use an interated
- // trapezoidal quadrature rule.
- const QTrapez<1> q1d;
- const QIterated<dim> q_iterated(q1d,map_degree);
+ // first we determine the support points on the unit cell in lexicographic
+ // order, which are (in accordance with MappingQ) the support points of
+ // QGaussLobatto.
+ const QGaussLobatto<dim> q_iterated(map_degree+1);
const unsigned int n_q_points = q_iterated.size();
- // we then need to define a renumbering
- // vector that allows us to go from a
- // lexicographic numbering scheme to a hierarchic
- // one. this fragment is taking almost verbatim
- // from the MappingQ class.
-
+ // we then need to define a renumbering vector that allows us to go from a
+ // lexicographic numbering scheme to a hierarchic one. this fragment is
+ // taking almost verbatim from the MappingQ class.
std::vector<unsigned int> renumber(n_q_points);
std::vector<unsigned int> dpo(dim+1, 1U);
for (unsigned int i=1; i<dpo.size(); ++i)
FETools::lexicographic_to_hierarchic_numbering (
FiniteElementData<dim> (dpo, 1, map_degree), renumber);
- // finally we assign the quadrature points in the
- // required order.
-
+ // finally we assign the quadrature points in the required order.
for (unsigned int q=0; q<n_q_points; ++q)
this->quadrature_points[renumber[q]] = q_iterated.point(q);
}
std::vector<Point<spacedim> > &a) const
{
- // first, basic assertion
- // with respect to vector size,
+ // first, basic assertion with respect to vector size,
const types::global_dof_index n_dofs = euler_dof_handler->n_dofs();
const types::global_dof_index vector_size = euler_vector->size();
AssertDimension(vector_size,n_dofs);
- // we then transform our tria iterator
- // into a dof iterator so we can
- // access data not associated with
- // triangulations
+ // we then transform our tria iterator into a dof iterator so we can access
+ // data not associated with triangulations
typename DoFHandler<dim,spacedim>::cell_iterator dof_cell(*cell, euler_dof_handler);
Assert (dof_cell->active() == true, ExcInactiveCell());
- // our quadrature rule is chosen
- // so that each quadrature point
- // corresponds to a support point
- // in the undeformed configuration.
- // we can then query the given
- // displacement field at these points
- // to determine the shift vector that
- // maps the support points to the
- // deformed configuration.
-
- // we assume that the given field contains
- // dim displacement components, but
- // that there may be other solution
- // components as well (e.g. pressures).
- // this class therefore assumes that the
- // first dim components represent the
- // actual shift vector we need, and simply
- // ignores any components after that.
- // this implies that the user should order
- // components appropriately, or create a
- // separate dof handler for the displacements.
+ // our quadrature rule is chosen so that each quadrature point corresponds
+ // to a support point in the undeformed configuration. we can then query
+ // the given displacement field at these points to determine the shift
+ // vector that maps the support points to the deformed configuration.
+
+ // we assume that the given field contains dim displacement components, but
+ // that there may be other solution components as well (e.g. pressures).
+ // this class therefore assumes that the first dim components represent the
+ // actual shift vector we need, and simply ignores any components after
+ // that. this implies that the user should order components appropriately,
+ // or create a separate dof handler for the displacements.
const unsigned int n_support_pts = support_quadrature.size();
const unsigned int n_components = euler_dof_handler->get_fe().n_components();
std::vector<Vector<double> > shift_vector(n_support_pts,Vector<double>(n_components));
- // fill shift vector for each
- // support point using an fe_values
- // object. make sure that the
- // fe_values variable isn't used
- // simulatenously from different
+ // fill shift vector for each support point using an fe_values object. make
+ // sure that the fe_values variable isn't used simulatenously from different
// threads
Threads::Mutex::ScopedLock lock(fe_values_mutex);
fe_values.reinit(dof_cell);
fe_values.get_function_values(*euler_vector, shift_vector);
- // and finally compute the positions of the
- // support points in the deformed
+ // and finally compute the positions of the support points in the deformed
// configuration.
-
a.resize(n_support_pts);
for (unsigned int q=0; q<n_support_pts; ++q)
{
std::vector<Point<spacedim> > &normal_vectors,
CellSimilarity::Similarity &cell_similarity) const
{
- // disable any previously detected
- // similarity and hand on to the respective
+ // disable any previously detected similarity and hand on to the respective
// function of the base class.
cell_similarity = CellSimilarity::invalid_next_cell;
MappingQ<dim,spacedim>::fill_fe_values (cell, q, mapping_data,
GridOutFlags::XFig::declare_parameters(param);
param.leave_subsection();
- param.enter_subsection("MathGl");
+ param.enter_subsection("MathGL");
GridOutFlags::MathGL::declare_parameters(param);
param.leave_subsection();
}
}
+
+template <int dim, int spacedim>
+const std::vector<Point<1> > &
+Boundary<dim,spacedim>::
+get_line_support_points (const unsigned int n_intermediate_points) const
+{
+ if (points.size() <= n_intermediate_points ||
+ points[n_intermediate_points].get() == 0)
+ {
+ Threads::Mutex::ScopedLock lock(mutex);
+ if (points.size() <= n_intermediate_points)
+ points.resize(n_intermediate_points+1);
+
+ // another thread might have created points in the meantime
+ if (points[n_intermediate_points].get() == 0)
+ {
+ std_cxx1x::shared_ptr<QGaussLobatto<1> >
+ quadrature (new QGaussLobatto<1>(n_intermediate_points+2));
+ points[n_intermediate_points] = quadrature;
+ }
+ }
+ return points[n_intermediate_points]->get_points();
+}
+
+
+
+
/* -------------------------- StraightBoundary --------------------- */
const unsigned int n=points.size();
Assert(n>0, ExcInternalError());
- const double dx=1./(n+1);
- double x=dx;
-
+ // Use interior points of QGaussLobatto quadrature formula support points
+ // for consistency with MappingQ
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(n);
const Point<spacedim> vertices[2] = { line->vertex(0),
line->vertex(1)
};
- for (unsigned int i=0; i<n; ++i, x+=dx)
- points[i] = (1-x)*vertices[0] + x*vertices[1];
+ for (unsigned int i=0; i<n; ++i)
+ {
+ const double x = line_points[i+1][0];
+ points[i] = (1-x)*vertices[0] + x*vertices[1];
+ }
}
const unsigned int n=points.size();
Assert(n>0, ExcInternalError());
- const double dx=1./(n+1);
- double x=dx;
+ // Use interior points of QGaussLobatto quadrature formula support points
+ // for consistency with MappingQ
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(n);
const Point<spacedim> vertices[2] = { line->vertex(0),
line->vertex(1)
};
- for (unsigned int i=0; i<n; ++i, x+=dx)
- points[i] = (1-x)*vertices[0] + x*vertices[1];
+ for (unsigned int i=0; i<n; ++i)
+ {
+ const double x = line_points[1+i][0];
+ points[i] = (1-x)*vertices[0] + x*vertices[1];
+ }
}
// is n a square number
Assert(m*m==n, ExcInternalError());
- const double ds=1./(m+1);
- double y=ds;
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(m);
const Point<spacedim> vertices[4] = { quad->vertex(0),
quad->vertex(1),
quad->vertex(3)
};
- for (unsigned int i=0; i<m; ++i, y+=ds)
+ for (unsigned int i=0; i<m; ++i)
{
- double x=ds;
- for (unsigned int j=0; j<m; ++j, x+=ds)
- points[i*m+j]=((1-x) * vertices[0] +
- x * vertices[1]) * (1-y) +
- ((1-x) * vertices[2] +
- x * vertices[3]) * y;
+ const double y=line_points[1+i][0];
+ for (unsigned int j=0; j<m; ++j)
+ {
+ const double x=line_points[1+j][0];
+ points[i*m+j]=((1-x) * vertices[0] +
+ x * vertices[1]) * (1-y) +
+ ((1-x) * vertices[2] +
+ x * vertices[3]) * y;
+ }
}
}
// is n a square number
Assert(m*m==n, ExcInternalError());
- const double ds=1./(m+1);
- double y=ds;
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(m);
const Point<spacedim> vertices[4] = { quad->vertex(0),
quad->vertex(1),
quad->vertex(3)
};
- for (unsigned int i=0; i<m; ++i, y+=ds)
+ for (unsigned int i=0; i<m; ++i)
{
- double x=ds;
- for (unsigned int j=0; j<m; ++j, x+=ds)
- points[i*m+j]=((1-x) * vertices[0] +
- x * vertices[1]) * (1-y) +
- ((1-x) * vertices[2] +
- x * vertices[3]) * y;
+ const double y=line_points[1+i][0];
+ for (unsigned int j=0; j<m; ++j)
+ {
+ const double x=line_points[1+j][0];
+ points[i*m+j]=((1-x) * vertices[0] +
+ x * vertices[1]) * (1-y) +
+ ((1-x) * vertices[2] +
+ x * vertices[3]) * y;
+ }
}
}
const unsigned int n=points.size();
Assert(n>0, ExcInternalError());
- // Do a simple linear interpolation
- // followed by projection, using
- // the same algorithm as above
- const Point<spacedim> ds = (v1-v0) / (n+1);
+ // Do a simple linear interpolation followed by projection, using the same
+ // algorithm as above
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(n);
for (unsigned int i=0; i<n; ++i)
{
- const Point<spacedim> middle = v0 + (i+1)*ds;
+ const double x = line_points[i+1][0];
+ const Point<spacedim> middle = (1-x)*v0 + x*v1;
const Point<spacedim> vector_from_axis = (middle-point_on_axis) -
((middle-point_on_axis) * direction) * direction;
{
const unsigned int n = points.size ();
const Point<dim> axis = x_1 - x_0;
- const Point<dim> dx = (p1 - p0) / (n + 1);
Assert (n > 0, ExcInternalError ());
- for (unsigned int i = 0; i < n; ++i)
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(n);
+
+ for (unsigned int i=0; i<n; ++i)
{
+ const double x = line_points[i+1][0];
+
// Compute the current point.
- const Point<dim> x_i = p0 + (i + 1) * dx;
- // To project this point on the
- // boundary of the cone we first
- // compute the orthogonal
- // projection of this point onto
- // the axis of the cone.
+ const Point<dim> x_i = (1-x)*p0 + x*p1;
+ // To project this point on the boundary of the cone we first compute
+ // the orthogonal projection of this point onto the axis of the cone.
const double c = (x_i - x_0) * axis / axis.square ();
const Point<dim> x_ip = x_0 + c * axis;
- // Compute the projection of
- // the middle point on the
- // boundary of the cone.
+ // Compute the projection of the middle point on the boundary of the
+ // cone.
points[i] = x_ip + get_radius (x_ip) * (x_i - x_ip) / (x_i - x_ip).norm ();
}
}
const Point<dim> axis = x_1 - x_0;
// Compute the middle point of the line.
const Point<dim> middle = StraightBoundary<dim>::get_new_point_on_line (line);
- // To project it on the boundary of
- // the cone we first compute the
- // orthogonal projection of the
- // middle point onto the axis of
- // the cone.
+ // To project it on the boundary of the cone we first compute the orthogonal
+ // projection of the middle point onto the axis of the cone.
const double c = (middle - x_0) * axis / axis.square ();
const Point<dim> middle_p = x_0 + c * axis;
- // Compute the projection of the
- // middle point on the boundary
- // of the cone.
+ // Compute the projection of the middle point on the boundary of the cone.
return middle_p + get_radius (middle_p) * (middle - middle_p) / (middle - middle_p).norm ();
}
const int dim = 3;
const Point<dim> axis = x_1 - x_0;
- // Compute the middle point of the
- // quad.
+ // Compute the middle point of the quad.
const Point<dim> middle = StraightBoundary<3>::get_new_point_on_quad (quad);
- // Same algorithm as above: To
- // project it on the boundary of
- // the cone we first compute the
- // orthogonal projection of the
- // middle point onto the axis of
- // the cone.
+ // Same algorithm as above: To project it on the boundary of the cone we
+ // first compute the orthogonal projection of the middle point onto the axis
+ // of the cone.
const double c = (middle - x_0) * axis / axis.square ();
const Point<dim> middle_p = x_0 + c * axis;
- // Compute the projection of the
- // middle point on the boundary
- // of the cone.
+ // Compute the projection of the middle point on the boundary of the cone.
return middle_p + get_radius (middle_p) * (middle - middle_p) / (middle - middle_p).norm ();
}
for (unsigned int vertex = 0; vertex < GeometryInfo<dim>::vertices_per_cell; ++vertex)
{
- // Compute the orthogonal
- // projection of the vertex onto
- // the axis of the cone.
+ // Compute the orthogonal projection of the vertex onto the axis of the
+ // cone.
const double c = (face->vertex (vertex) - x_0) * axis / axis.square ();
const Point<dim> vertex_p = x_0 + c * axis;
- // Then compute the vector
- // pointing from the point
- // <tt>vertex_p</tt> on the axis
- // to the vertex.
+ // Then compute the vector pointing from the point <tt>vertex_p</tt> on
+ // the axis to the vertex.
const Point<dim> axis_to_vertex = face->vertex (vertex) - vertex_p;
face_vertex_normals[vertex] = axis_to_vertex / axis_to_vertex.norm ();
Assert(std::fabs(v1.square()-r2)<eps*r2, ExcInternalError());
const double alpha=std::acos((v0*v1)/std::sqrt(v0.square()*v1.square()));
- const double d_alpha=alpha/(n+1);
const Point<spacedim> pm=0.5*(v0+v1);
const double h=std::sqrt(pm.square());
- double beta=0;
- unsigned int left_index=0, right_index=0;
- if ((n+1)%2==0)
- {
- // if the number of
- // parts is even insert
- // the midpoint
- left_index=(n-1)/2;
- right_index=left_index;
- points[left_index]=pm;
- --left_index;
- ++right_index;
- beta=d_alpha;
- }
- else
- {
- beta=(n/2+1)*d_alpha-alpha/2.;
- right_index=n/2;
- left_index=n/2-1;
- }
-
// n even: m=n/2,
// n odd: m=(n-1)/2
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(n);
const unsigned int m=n/2;
- for (unsigned int i=0; i<m ; ++i, ++right_index, --left_index, beta+=d_alpha)
+ for (unsigned int i=0; i<m ; ++i)
{
- Assert(right_index<n, ExcInternalError());
- Assert(left_index+1>=1, ExcInternalError());
-
- double d=h*std::tan(beta);
- points[right_index]=pm+d/length*(v1-v0);
- points[left_index]=pm-d/length*(v1-v0);
+ const double beta = alpha * (line_points[i+1][0]-0.5);
+ const double d=h*std::tan(beta);
+ points[i]=pm+d/length*(v1-v0);
+ points[n-1-i]=pm-d/length*(v1-v0);
}
+ if ((n+1)%2==0)
+ // if the number of parts is even insert the midpoint
+ points[(n-1)/2]=pm;
- // project the points from the
- // straight line to the
- // HyperBallBoundary
+
+ // project the points from the straight line to the HyperBallBoundary
for (unsigned int i=0; i<n; ++i)
{
points[i] *= r / std::sqrt(points[i].square());
get_intermediate_points_on_line (const typename Triangulation<dim>::line_iterator &line,
std::vector<Point<dim> > &points) const
{
- // check whether center of object is
- // at x==0, since then it belongs
- // to the plane part of the
- // boundary
+ // check whether center of object is at x==0, since then it belongs to the
+ // plane part of the boundary
const Point<dim> line_center = line->center();
if (line_center(0) == this->center(0))
return StraightBoundary<dim>::get_intermediate_points_on_line (line, points);
points[0]=get_new_point_on_quad(quad);
else
{
- // check whether center of
- // object is at x==0, since
- // then it belongs to the plane
- // part of the boundary
+ // check whether center of object is at x==0, since then it belongs to
+ // the plane part of the boundary
const Point<dim> quad_center = quad->center();
if (quad_center(0) == this->center(0))
StraightBoundary<dim>::get_intermediate_points_on_quad (quad, points);
get_normals_at_vertices (const typename Triangulation<dim>::face_iterator &face,
typename Boundary<dim>::FaceVertexNormals &face_vertex_normals) const
{
- // check whether center of object is
- // at x==0, since then it belongs
- // to the plane part of the
- // boundary
+ // check whether center of object is at x==0, since then it belongs to the
+ // plane part of the boundary
const Point<dim> quad_center = face->center();
if (quad_center(0) == this->center(0))
StraightBoundary<dim>::get_normals_at_vertices (face, face_vertex_normals);
{
switch (dim)
{
- // in 2d, first check whether the two
- // end points of the line are on the
- // axis of symmetry. if so, then return
- // the mid point
+ // in 2d, first check whether the two end points of the line are on the
+ // axis of symmetry. if so, then return the mid point
case 2:
{
if ((line->vertex(0)(0) == this->center(0))
(line->vertex(1)(0) == this->center(0)))
return (line->vertex(0) + line->vertex(1))/2;
else
- // otherwise we are on the outer or
- // inner part of the shell. proceed
+ // otherwise we are on the outer or inner part of the shell. proceed
// as in the base class
return HyperShellBoundary<dim>::get_new_point_on_line (line);
}
- // in 3d, a line is a straight
- // line if it is on the symmetry
- // plane and if not both of its
- // end points are on either the
- // inner or outer sphere
+ // in 3d, a line is a straight line if it is on the symmetry plane and if
+ // not both of its end points are on either the inner or outer sphere
case 3:
{
- outer_radius) < 1e-12 * outer_radius))))
return (line->vertex(0) + line->vertex(1))/2;
else
- // otherwise we are on the outer or
- // inner part of the shell. proceed
+ // otherwise we are on the outer or inner part of the shell. proceed
// as in the base class
return HyperShellBoundary<dim>::get_new_point_on_line (line);
}
HalfHyperShellBoundary<dim>::
get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const
{
- // if this quad is on the symmetry plane,
- // take the center point and project it
- // outward to the same radius as the
- // centers of the two radial lines
+ // if this quad is on the symmetry plane, take the center point and project
+ // it outward to the same radius as the centers of the two radial lines
if ((quad->vertex(0)(0) == this->center(0)) &&
(quad->vertex(1)(0) == this->center(0)) &&
(quad->vertex(2)(0) == this->center(0)) &&
Assert (false, ExcInternalError());
}
- // otherwise we are on the outer or
- // inner part of the shell. proceed
- // as in the base class
+ // otherwise we are on the outer or inner part of the shell. proceed as in
+ // the base class
return HyperShellBoundary<dim>::get_new_point_on_quad (quad);
}
{
switch (dim)
{
- // in 2d, first check whether the two
- // end points of the line are on the
- // axis of symmetry. if so, then return
- // the mid point
+ // in 2d, first check whether the two end points of the line are on the
+ // axis of symmetry. if so, then return the mid point
case 2:
{
if ((line->vertex(0)(0) == this->center(0))
(line->vertex(1)(0) == this->center(0)))
StraightBoundary<dim>::get_intermediate_points_on_line (line, points);
else
- // otherwise we are on the outer or
- // inner part of the shell. proceed
+ // otherwise we are on the outer or inner part of the shell. proceed
// as in the base class
HyperShellBoundary<dim>::get_intermediate_points_on_line (line, points);
break;
}
- // in 3d, a line is a straight
- // line if it is on the symmetry
- // plane and if not both of its
- // end points are on either the
- // inner or outer sphere
+ // in 3d, a line is a straight line if it is on the symmetry plane and if
+ // not both of its end points are on either the inner or outer sphere
case 3:
{
if (((line->vertex(0)(0) == this->center(0))
- outer_radius) < 1e-12 * outer_radius))))
StraightBoundary<dim>::get_intermediate_points_on_line (line, points);
else
- // otherwise we are on the outer or
- // inner part of the shell. proceed
+ // otherwise we are on the outer or inner part of the shell. proceed
// as in the base class
HyperShellBoundary<dim>::get_intermediate_points_on_line (line, points);
{
Assert (dim < 3, ExcNotImplemented());
- // check whether center of object is
- // at x==0, since then it belongs
- // to the plane part of the
- // boundary
+ // check whether center of object is at x==0, since then it belongs to the
+ // plane part of the boundary
const Point<dim> quad_center = quad->center();
if (quad_center(0) == this->center(0))
StraightBoundary<dim>::get_intermediate_points_on_quad (quad, points);
Point<2> middle(0,0);
- //Take care for periodic conditions,
- //For instance phi0= 0, phi1= 3/2*Pi middle has to be 7/4*Pi not 3/4*Pi
- //This also works for -Pi/2 + Pi, middle is 5/4*Pi
+ //Take care for periodic conditions, For instance phi0= 0, phi1= 3/2*Pi
+ //middle has to be 7/4*Pi not 3/4*Pi. This also works for -Pi/2 + Pi, middle
+ //is 5/4*Pi
for (unsigned int i=0; i<2; i++)
if (std::abs(p0(i)-p1(i))> numbers::PI)
middle(i)=2*numbers::PI;
get_intermediate_points_on_line (const Triangulation<2, 3>::line_iterator &line,
std::vector< Point< 3 > > &points) const
{
- //Almost the same implementation as StraightBoundary<2,3>
+ //Almost the same implementation as StraightBoundary<2,3>
unsigned int npoints=points.size();
if (npoints==0) return;
offset[0]=0;
offset[1]=0;
- //Take care for periodic conditions & negative angles,
- //see get_new_point_on_line() above
- //Because we dont have a symmetric interpolation (just the middle) we need to
- //add 2*Pi to each almost zero and negative angles.
+ //Take care for periodic conditions & negative angles, see
+ //get_new_point_on_line() above. Because we dont have a symmetric
+ //interpolation (just the middle) we need to add 2*Pi to each almost zero
+ //and negative angles.
for (unsigned int i=0; i<2; i++)
for (unsigned int j=1; j<2; j++)
{
p[j](i)+=2*numbers::PI*offset[i];
- double dx=1.0/(npoints+1);
- double x=dx;
Point<2> target;
- for (unsigned int i=0; i<npoints; i++,x+=dx)
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(npoints);
+ for (unsigned int i=0; i<npoints; i++)
{
+ const double x = line_points[i+1][0];
target= (1-x)*p[0] + x*p[1];
points[i]=get_real_coord(target);
}
// is n a square number
Assert(m*m==n, ExcInternalError());
- const double ds=1./(m+1);
- double y=ds;
-
Point<2> p[4];
for (unsigned int i=0; i<4; i++)
offset[0]=0;
offset[1]=0;
- //Take care for periodic conditions & negative angles,
- //see get_new_point_on_line() above
- //Because we dont have a symmetric interpolation (just the middle) we need to
- //add 2*Pi to each almost zero and negative angles.
+ //Take care for periodic conditions & negative angles, see
+ //get_new_point_on_line() above. Because we dont have a symmetric
+ //interpolation (just the middle) we need to add 2*Pi to each almost zero
+ //and negative angles.
for (unsigned int i=0; i<2; i++)
for (unsigned int j=1; j<4; j++)
{
if (p[j](i)<1.E-12 ) //Take care for periodic conditions & negative angles
p[j](i)+=2*numbers::PI*offset[i];
- for (unsigned int i=0; i<m; ++i, y+=ds)
+ const std::vector<Point<1> > &line_points = this->get_line_support_points(m);
+ for (unsigned int i=0; i<m; ++i)
{
- double x=ds;
- for (unsigned int j=0; j<m; ++j, x+=ds)
+ const double y=line_points[i+1][0];
+ for (unsigned int j=0; j<m; ++j)
{
+ const double x=line_points[j+1][0];
target=((1-x) * p[0] +
x * p[1]) * (1-y) +
((1-x) * p[2] +
:
solver_control (cn),
mpi_communicator (mpi_communicator),
- target_eigenvalue (PETSC_NULL),
+ target_eigenvalue (0.),
set_which (EPS_LARGEST_MAGNITUDE),
set_problem (EPS_NHEP),
opA (NULL),
}
void
- SolverBase::solve (const size_type n_eigenpairs,
- size_type *n_converged)
+ SolverBase::solve (const unsigned int n_eigenpairs,
+ unsigned int *n_converged)
{
int ierr;
AssertThrow (ierr == 0, ExcSLEPcError(ierr));
}
- // set transformation type if any
+ // if a spectral transformation is to be used, set the
+ // transformation and target the wanted eigenvalues
if (transformation)
- transformation->set_context (solver_data->eps);
-
- // set target eigenvalues to solve for
- ierr = EPSSetTarget (solver_data->eps, target_eigenvalue);
- AssertThrow (ierr == 0, ExcSLEPcError(ierr));
+ {
+ // set transformation type if any
+ transformation->set_context (solver_data->eps);
+
+ // set target eigenvalues to solve for
+ ierr = EPSSetTarget (solver_data->eps, target_eigenvalue);
+ AssertThrow (ierr == 0, ExcSLEPcError(ierr));
+ }
// set which portion of the eigenspectrum to solve for
ierr = EPSSetWhichEigenpairs (solver_data->eps, set_which);
// get number of converged eigenstates
ierr = EPSGetConverged (solver_data->eps,
- reinterpret_cast<PetscInt *>(n_converged));
+ reinterpret_cast<PetscInt*>(n_converged));
AssertThrow (ierr == 0, ExcSLEPcError(ierr));
- PetscInt n_iterations = 0;
- double residual_norm = 1e300;
+ PetscInt n_iterations = 0;
+ PetscReal residual_norm = 1.e300;
// @todo Investigate elaborating on some of this to act on the
// complete eigenspectrum
ierr = EPSGetIterationNumber (solver_data->eps, &n_iterations);
AssertThrow (ierr == 0, ExcSLEPcError(ierr));
- // get the residual norm of the most extreme eigenvalue
- ierr = EPSComputeResidualNorm (solver_data->eps, 0, &residual_norm);
- AssertThrow (ierr == 0, ExcSLEPcError(ierr));
+ // get the residual norm of the most extreme eigenvalue if and
+ // only if at least one eigenvector has converged.
+ if ((*n_converged)>0)
+ {
+ ierr = EPSComputeResidualNorm (solver_data->eps, 0, &residual_norm);
+ AssertThrow (ierr == 0, ExcSLEPcError(ierr));
+ }
// check the solver state
const SolverControl::State state
}
void
- SolverBase::get_eigenpair (const size_type index,
+ SolverBase::get_eigenpair (const unsigned int index,
PetscScalar &eigenvalues,
PETScWrappers::VectorBase &eigenvectors)
{
SET(_src
data_out.cc
+ data_out_dof_data.cc
data_out_faces.cc
data_out_rotation.cc
data_out_stack.cc
derivative_approximation.cc
dof_output_operator.cc
error_estimator.cc
+ error_estimator_1d.cc
fe_field_function.cc
matrix_tools.cc
histogram.cc
point_value_history.cc
solution_transfer.cc
solution_transfer_inst2.cc
+ solution_transfer_inst3.cc
+ solution_transfer_inst4.cc
time_dependent.cc
- vector_tools.cc
+ vector_tools_boundary.cc
+ vector_tools_constraints.cc
+ vector_tools_integrate_difference.cc
+ vector_tools_interpolate.cc
+ vector_tools_mean_value.cc
+ vector_tools_point_value.cc
+ vector_tools_project.cc
+ vector_tools_rhs.cc
)
SET(_inst
- data_out_faces.inst.in
data_out.inst.in
+ data_out_dof_data.inst.in
+ data_out_faces.inst.in
data_out_rotation.inst.in
data_out_stack.inst.in
data_postprocessor.inst.in
derivative_approximation.inst.in
dof_output_operator.inst.in
error_estimator.inst.in
+ error_estimator_1d.inst.in
fe_field_function.inst.in
matrix_tools.inst.in
point_value_history.inst.in
solution_transfer.inst.in
time_dependent.inst.in
- vector_tools.inst.in
+ vector_tools_boundary.inst.in
+ vector_tools_constraints.inst.in
+ vector_tools_integrate_difference.inst.in
+ vector_tools_interpolate.inst.in
+ vector_tools_mean_value.inst.in
+ vector_tools_point_value.inst.in
+ vector_tools_project.inst.in
+ vector_tools_rhs.inst.in
)
DEAL_II_ADD_LIBRARY(obj_numerics OBJECT ${_src} ${_header} ${_inst})
//
// ---------------------------------------------------------------------
-#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/work_stream.h>
-#include <deal.II/base/memory_consumption.h>
-#include <deal.II/lac/vector.h>
-#include <deal.II/lac/block_vector.h>
-#include <deal.II/lac/parallel_vector.h>
-#include <deal.II/lac/parallel_block_vector.h>
-#include <deal.II/lac/petsc_vector.h>
-#include <deal.II/lac/petsc_block_vector.h>
-#include <deal.II/lac/trilinos_vector.h>
-#include <deal.II/lac/trilinos_block_vector.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/grid/tria.h>
#include <deal.II/dofs/dof_handler.h>
{
namespace DataOut
{
- template <int dim, int spacedim>
- ParallelDataBase<dim,spacedim>::
- ParallelDataBase (const unsigned int n_datasets,
- const unsigned int n_subdivisions,
- const std::vector<unsigned int> &n_postprocessor_outputs,
- const Mapping<dim,spacedim> &mapping,
- const std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<dim,spacedim> > > &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<dim>
- quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
- n_q_points = quadrature[0].size();
- x_fe_values.resize(this->finite_elements.size());
- for (unsigned int i=0; i<this->finite_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; j<i; ++j)
- if (this->finite_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<dim,spacedim>
- (this->mapping_collection,
- *this->finite_elements[i],
- quadrature,
- this->update_flags));
- }
- }
- else
- {
- dealii::hp::QCollection<dim-1>
- quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
- n_q_points = quadrature[0].size();
- x_fe_face_values.resize(this->finite_elements.size());
- for (unsigned int i=0; i<this->finite_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; j<i; ++j)
- if (this->finite_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<dim,spacedim>
- (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.size(); ++dataset)
- if (n_postprocessor_outputs[dataset] != 0)
- postprocessed_values[dataset]
- .resize(n_q_points,
- dealii::Vector<double>(n_postprocessor_outputs[dataset]));
- }
-
-
-
-
-
- // implement copy constructor to create a thread's own version of
- // x_fe_values
- template <int dim, int spacedim>
- ParallelDataBase<dim,spacedim>::
- ParallelDataBase (const ParallelDataBase<dim,spacedim> &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<dim>
- quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
- x_fe_values.resize(this->finite_elements.size());
- for (unsigned int i=0; i<this->finite_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; j<i; ++j)
- if (this->finite_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<dim,spacedim>
- (this->mapping_collection,
- *this->finite_elements[i],
- quadrature,
- this->update_flags));
- }
- }
- else
- {
- dealii::hp::QCollection<dim-1>
- quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
- x_fe_face_values.resize(this->finite_elements.size());
- for (unsigned int i=0; i<this->finite_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; j<i; ++j)
- if (this->finite_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<dim,spacedim>
- (this->mapping_collection,
- *this->finite_elements[i],
- quadrature,
- this->update_flags));
- }
- }
- }
-
-
-
- template <int dim, int spacedim>
- template <typename DH>
- void
- ParallelDataBase<dim,spacedim>::
- reinit_all_fe_values(std::vector<std_cxx1x::shared_ptr<DataEntryBase<DH> > > &dof_data,
- const typename dealii::Triangulation<dim,spacedim>::cell_iterator &cell,
- const unsigned int face)
- {
- for (unsigned int dataset=0; dataset<dof_data.size(); ++dataset)
- {
- bool duplicate = false;
- for (unsigned int j=0; j<dataset; ++j)
- if (finite_elements[dataset].get() == finite_elements[j].get())
- duplicate = true;
- if (duplicate == false)
- {
- typename DH::active_cell_iterator dh_cell(&cell->get_triangulation(),
- cell->level(),
- cell->index(),
- dof_data[dataset]->dof_handler);
- if (x_fe_values.empty())
- {
- AssertIndexRange(face,
- GeometryInfo<dim>::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<dim>::faces_per_cell);
- x_fe_face_values[0]->reinit(cell, face);
- }
- else
- x_fe_values[0]->reinit (cell);
- }
- }
-
-
-
- template <int dim, int spacedim>
- const FEValuesBase<dim,spacedim> &
- ParallelDataBase<dim,spacedim>::
- 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 <int dim, int spacedim>
- void
- ParallelDataBase<dim,spacedim>::
- 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<patch_values_system.size(); ++k)
- {
- patch_values_system[k].reinit(n_components);
- patch_gradients_system[k].resize(n_components);
- patch_hessians_system[k].resize(n_components);
- }
- }
-
-
-
-
template <int dim, int spacedim>
ParallelData<dim,spacedim>::
ParallelData (const unsigned int n_datasets,
-
/**
* In a WorkStream context, use this function to append the patch computed
* by the parallel stage to the array of patches.
}
-namespace internal
-{
- namespace DataOut
- {
- template <class DH>
- DataEntryBase<DH>::DataEntryBase (const DH *dofs,
- const std::vector<std::string> &names_in,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
- :
- dof_handler (dofs, typeid(dealii::DataOut_DoFData<DH,DH::dimension,DH::space_dimension>).name()),
- names(names_in),
- data_component_interpretation (data_component_interpretation),
- postprocessor(0, typeid(*this).name()),
- n_output_variables(names.size())
- {
- Assert (names.size() == data_component_interpretation.size(),
- ExcDimensionMismatch(data_component_interpretation.size(),
- names.size()));
-
- // check that the names use only allowed characters
- for (unsigned int i=0; i<names.size(); ++i)
- Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789_<>()") == std::string::npos,
- typename dealii::DataOut<DH::dimension>::
- ExcInvalidCharacter (names[i],
- names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789_<>()")));
- }
-
-
-
- template <class DH>
- DataEntryBase<DH>::DataEntryBase (const DH *dofs,
- const DataPostprocessor<DH::space_dimension> *data_postprocessor)
- :
- dof_handler (dofs, typeid(dealii::DataOut_DoFData<DH,DH::dimension,DH::space_dimension>).name()),
- names(data_postprocessor->get_names()),
- data_component_interpretation (data_postprocessor->get_data_component_interpretation()),
- postprocessor(data_postprocessor, typeid(*this).name()),
- n_output_variables(names.size())
- {
- Assert (data_postprocessor->get_names().size()
- ==
- data_postprocessor->get_data_component_interpretation().size(),
- ExcDimensionMismatch (data_postprocessor->get_names().size(),
- data_postprocessor->get_data_component_interpretation().size()));
-
- // check that the names use only allowed characters
- for (unsigned int i=0; i<names.size(); ++i)
- Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789_<>()") == std::string::npos,
- typename dealii::DataOut<DH::dimension>::
- ExcInvalidCharacter (names[i],
- names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789_<>()")));
- }
-
-
-
- template <class DH>
- DataEntryBase<DH>::~DataEntryBase ()
- {}
-
-
-
- /**
- * Class that stores a pointer to a vector of type equal to the template
- * argument, and provides the functions to extract data from it.
- *
- * @author Wolfgang Bangerth, 2004
- */
- template <class DH, typename VectorType>
- class DataEntry : public DataEntryBase<DH>
- {
- 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.
- */
- DataEntry (const DH *dofs,
- const VectorType *data,
- const std::vector<std::string> &names,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &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.
- */
- DataEntry (const DH *dofs,
- const VectorType *data,
- const DataPostprocessor<DH::space_dimension> *data_postprocessor);
-
- /**
- * Assuming that the stored vector is a cell vector, extract the given
- * element from it.
- */
- virtual
- double
- 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.
- */
- virtual
- void
- get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<double> &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.
- */
- virtual
- void
- get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<dealii::Vector<double> > &patch_values_system) const;
-
- /**
- * Given a FEValuesBase object, extract the gradients on the present
- * cell from the vector we actually store.
- */
- virtual
- void
- get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<Tensor<1,DH::space_dimension> > &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.
- */
- virtual
- void
- get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<std::vector<Tensor<1,DH::space_dimension> > > &patch_gradients_system) const;
-
- /**
- * Given a FEValuesBase object, extract the second derivatives on the
- * present cell from the vector we actually store.
- */
- virtual
- void
- get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<Tensor<2,DH::space_dimension> > &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.
- */
- virtual
- void
- get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<std::vector< Tensor<2,DH::space_dimension> > > &patch_hessians_system) const;
-
- /**
- * Clear all references to the vectors.
- */
- virtual void clear ();
-
- /**
- * 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.
- */
- const VectorType *vector;
- };
-
-
-
- template <class DH, class VectorType>
- DataEntry<DH,VectorType>::
- DataEntry (const DH *dofs,
- const VectorType *data,
- const std::vector<std::string> &names,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
- :
- DataEntryBase<DH> (dofs, names, data_component_interpretation),
- vector (data)
- {}
-
-
-
- template <class DH, class VectorType>
- DataEntry<DH,VectorType>::
- DataEntry (const DH *dofs,
- const VectorType *data,
- const DataPostprocessor<DH::space_dimension> *data_postprocessor)
- :
- DataEntryBase<DH> (dofs, data_postprocessor),
- vector (data)
- {}
-
-
- namespace
- {
- template <class VectorType>
- double
- get_vector_element (const VectorType &vector,
- const unsigned int cell_number)
- {
- return vector[cell_number];
- }
-
-
- double
- get_vector_element (const IndexSet &is,
- const unsigned int cell_number)
- {
- return (is.is_element(cell_number) ? 1 : 0);
- }
- }
-
-
-
- template <class DH, class VectorType>
- double
- DataEntry<DH,VectorType>::
- get_cell_data_value (const unsigned int cell_number) const
- {
- return get_vector_element(*vector, cell_number);
- }
-
-
-
- template <class DH, class VectorType>
- void
- DataEntry<DH,VectorType>::
- get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<dealii::Vector<double> > &patch_values_system) const
- {
- fe_patch_values.get_function_values (*vector, patch_values_system);
- }
-
-
-
- template <class DH, typename VectorType>
- void
- DataEntry<DH,VectorType>::
- get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<double> &patch_values) const
- {
- fe_patch_values.get_function_values (*vector, patch_values);
- }
-
-
-
- template <class DH, class VectorType>
- void
- DataEntry<DH,VectorType>::
- get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<std::vector<Tensor<1,DH::space_dimension> > > &patch_gradients_system) const
- {
- fe_patch_values.get_function_gradients (*vector, patch_gradients_system);
- }
-
-
-
- template <class DH, typename VectorType>
- void
- DataEntry<DH,VectorType>::
- get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<Tensor<1,DH::space_dimension> > &patch_gradients) const
- {
- fe_patch_values.get_function_gradients (*vector, patch_gradients);
- }
-
-
-
- template <class DH, class VectorType>
- void
- DataEntry<DH,VectorType>::
- get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<std::vector<Tensor<2,DH::space_dimension> > > &patch_hessians_system) const
- {
- fe_patch_values.get_function_hessians (*vector, patch_hessians_system);
- }
-
-
-
- template <class DH, typename VectorType>
- void
- DataEntry<DH,VectorType>::
- get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
- std::vector<Tensor<2,DH::space_dimension> > &patch_hessians) const
- {
- fe_patch_values.get_function_hessians (*vector, patch_hessians);
- }
-
-
-
- template <class DH, typename VectorType>
- std::size_t
- DataEntry<DH,VectorType>::memory_consumption () const
- {
- return (sizeof (vector) +
- MemoryConsumption::memory_consumption (this->names));
- }
-
-
-
- template <class DH, class VectorType>
- void
- DataEntry<DH,VectorType>::clear ()
- {
- vector = 0;
- this->dof_handler = 0;
- }
- }
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::DataOut_DoFData ()
- :
- triangulation(0,typeid(*this).name()),
- dofs(0,typeid(*this).name())
-{}
-
-
-
-template <class DH, int patch_dim, int patch_space_dim>
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::~DataOut_DoFData ()
-{
- clear ();
-}
-
-
-
-template <class DH, int patch_dim, int patch_space_dim>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-attach_dof_handler (const DH &d)
-{
- Assert (dof_data.size() == 0, ExcOldDataStillPresent());
- Assert (cell_data.size() == 0, ExcOldDataStillPresent());
-
- triangulation = SmartPointer<const Triangulation<DH::dimension,DH::space_dimension> >(&d.get_tria(), typeid(*this).name());
- dofs = SmartPointer<const DH>(&d, typeid(*this).name());
-}
-
-
-
-template <class DH, int patch_dim, int patch_space_dim>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-attach_triangulation (const Triangulation<DH::dimension,DH::space_dimension> &tria)
-{
- Assert (dof_data.size() == 0, ExcOldDataStillPresent());
- Assert (cell_data.size() == 0, ExcOldDataStillPresent());
-
- triangulation = SmartPointer<const Triangulation<DH::dimension,DH::space_dimension> >(&tria, typeid(*this).name());
-}
-
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-template <class VECTOR>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-add_data_vector (const VECTOR &vec,
- const std::string &name,
- const DataVectorType type,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
-{
- Assert (triangulation != 0, ExcNoTriangulationSelected ());
- const unsigned int n_components =
- dofs != 0 ? dofs->get_fe().n_components () : 1;
-
- std::vector<std::string> names;
- // if only one component or vector is cell vector: we only need one name
- if ((n_components == 1) ||
- (vec.size() == triangulation->n_active_cells()))
- {
- names.resize (1, name);
- }
- else
- // otherwise append _i to the given name
- {
- names.resize (n_components);
- for (unsigned int i=0; i<n_components; ++i)
- {
- std::ostringstream namebuf;
- namebuf << '_' << i;
- names[i] = name + namebuf.str();
- }
- }
-
- add_data_vector (vec, names, type, data_component_interpretation);
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-template <class VECTOR>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-add_data_vector (const VECTOR &vec,
- const std::vector<std::string> &names,
- const DataVectorType type,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation_)
-{
- Assert (triangulation != 0, ExcNoTriangulationSelected ());
-
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &
- data_component_interpretation
- = (data_component_interpretation_.size() != 0
- ?
- data_component_interpretation_
- :
- std::vector<DataComponentInterpretation::DataComponentInterpretation>
- (names.size(), DataComponentInterpretation::component_is_scalar));
-
- // either cell data and one name,
- // or dof data and n_components names
- DataVectorType actual_type = type;
- if (type == type_automatic)
- {
- if (vec.size() == triangulation->n_active_cells())
- actual_type = type_cell_data;
- else
- actual_type = type_dof_data;
- }
-
- switch (actual_type)
- {
- case type_cell_data:
- 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(),
- 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...
- Assert (false, ExcInternalError());
- }
-
- internal::DataOut::DataEntryBase<DH> *new_entry
- = new internal::DataOut::DataEntry<DH,VECTOR>(dofs, &vec, names,
- data_component_interpretation);
- if (actual_type == type_dof_data)
- dof_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
- else
- cell_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-template <class VECTOR>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-add_data_vector (const VECTOR &vec,
- const DataPostprocessor<DH::space_dimension> &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
-
- Assert (dofs != 0, ExcNoDoFHandlerSelected ());
-
- Assert (vec.size() == dofs->n_dofs(),
- ExcInvalidVectorSize (vec.size(),
- dofs->n_dofs(),
- dofs->get_tria().n_active_cells()));
-
- internal::DataOut::DataEntryBase<DH> *new_entry
- = new internal::DataOut::DataEntry<DH,VECTOR>(dofs, &vec, &data_postprocessor);
- dof_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-template <class VECTOR>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-add_data_vector (const DH &dof_handler,
- const VECTOR &vec,
- const DataPostprocessor<DH::space_dimension> &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<DH> *new_entry
- = new internal::DataOut::DataEntry<DH,VECTOR>(&dof_handler, &vec, &data_postprocessor);
- dof_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-template <class VECTOR>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-add_data_vector (const DH &dof_handler,
- const VECTOR &data,
- const std::string &name,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
-{
- const unsigned int n_components = dof_handler.get_fe().n_components ();
-
- std::vector<std::string> 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<n_components; ++i)
- {
- std::ostringstream namebuf;
- namebuf << '_' << i;
- names[i] = name + namebuf.str();
- }
- }
-
- add_data_vector (dof_handler, data, names, data_component_interpretation);
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-template <class VECTOR>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-add_data_vector (const DH &dof_handler,
- const VECTOR &data,
- const std::vector<std::string> &names,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &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<const Triangulation<DH::dimension,DH::space_dimension> >(&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<DataComponentInterpretation::DataComponentInterpretation> &
- data_component_interpretation
- = (data_component_interpretation_.size() != 0
- ?
- data_component_interpretation_
- :
- std::vector<DataComponentInterpretation::DataComponentInterpretation>
- (names.size(), DataComponentInterpretation::component_is_scalar));
-
- internal::DataOut::DataEntryBase<DH> *new_entry
- = new internal::DataOut::DataEntry<DH,VECTOR>(&dof_handler, &data, names,
- data_component_interpretation);
- dof_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-void DataOut_DoFData<DH,patch_dim,patch_space_dim>::clear_data_vectors ()
-{
- dof_data.erase (dof_data.begin(), dof_data.end());
- cell_data.erase (cell_data.begin(), cell_data.end());
-
- // delete patches
- std::vector<Patch> dummy;
- patches.swap (dummy);
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-clear_input_data_references ()
-{
- for (unsigned int i=0; i<dof_data.size(); ++i)
- dof_data[i]->clear ();
-
- for (unsigned int i=0; i<cell_data.size(); ++i)
- cell_data[i]->clear ();
-
- if (dofs != 0)
- dofs = 0;
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-void
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::clear ()
-{
- dof_data.erase (dof_data.begin(), dof_data.end());
- cell_data.erase (cell_data.begin(), cell_data.end());
-
- if (dofs != 0)
- dofs = 0;
-
- // delete patches
- std::vector<Patch> dummy;
- patches.swap (dummy);
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-std::vector<std::string>
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::
-get_dataset_names () const
-{
- std::vector<std::string> names;
- // collect the names of dof
- // and cell data
- typedef
- typename std::vector<std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> > >::const_iterator
- data_iterator;
-
- for (data_iterator d=dof_data.begin();
- d!=dof_data.end(); ++d)
- for (unsigned int i=0; i<(*d)->names.size(); ++i)
- names.push_back ((*d)->names[i]);
- for (data_iterator d=cell_data.begin(); d!=cell_data.end(); ++d)
- {
- Assert ((*d)->names.size() == 1, ExcInternalError());
- names.push_back ((*d)->names[0]);
- }
-
- return names;
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::get_vector_data_ranges () const
-{
- std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >
- ranges;
-
- // collect the ranges of dof
- // and cell data
- typedef
- typename std::vector<std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> > >::const_iterator
- data_iterator;
-
- unsigned int output_component = 0;
- for (data_iterator d=dof_data.begin();
- d!=dof_data.end(); ++d)
- for (unsigned int i=0; i<(*d)->n_output_variables;
- ++i, ++output_component)
- // see what kind of data we have
- // here. note that for the purpose of
- // the current function all we care
- // about is vector data
- if ((*d)->data_component_interpretation[i] ==
- DataComponentInterpretation::component_is_part_of_vector)
- {
- // ensure that there is a
- // continuous number of next
- // space_dim components that all
- // deal with vectors
- Assert (i+patch_space_dim <=
- (*d)->n_output_variables,
- ExcInvalidVectorDeclaration (i,
- (*d)->names[i]));
- for (unsigned int dd=1; dd<patch_space_dim; ++dd)
- Assert ((*d)->data_component_interpretation[i+dd]
- ==
- DataComponentInterpretation::component_is_part_of_vector,
- ExcInvalidVectorDeclaration (i,
- (*d)->names[i]));
-
- // all seems alright, so figure out
- // whether there is a common name
- // to these components. if not,
- // leave the name empty and let the
- // output format writer decide what
- // to do here
- std::string name = (*d)->names[i];
- for (unsigned int dd=1; dd<patch_space_dim; ++dd)
- if (name != (*d)->names[i+dd])
- {
- name = "";
- break;
- }
-
- // finally add a corresponding
- // range
- std_cxx1x::tuple<unsigned int, unsigned int, std::string>
- range (output_component,
- output_component+patch_space_dim-1,
- name);
-
- ranges.push_back (range);
-
- // increase the 'component' counter
- // by the appropriate amount, same
- // for 'i', since we have already
- // dealt with all these components
- output_component += patch_space_dim-1;
- i += patch_space_dim-1;
- }
-
- // note that we do not have to traverse the
- // list of cell data here because cell data
- // is one value per (logical) cell and
- // therefore cannot be a vector
-
- // as a final check, the 'component'
- // counter should be at the total number of
- // components added up now
-#ifdef DEBUG
- unsigned int n_output_components = 0;
- for (data_iterator d=dof_data.begin();
- d!=dof_data.end(); ++d)
- n_output_components += (*d)->n_output_variables;
- Assert (output_component == n_output_components,
- ExcInternalError());
-#endif
-
- return ranges;
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-const std::vector< dealii::DataOutBase::Patch<patch_dim, patch_space_dim> > &
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::get_patches () const
-{
- return patches;
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<DH::dimension,DH::space_dimension> > >
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::get_finite_elements() const
-{
- const unsigned int dhdim = DH::dimension;
- const unsigned int dhspacedim = DH::space_dimension;
- std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<dhdim,dhspacedim> > >
- finite_elements(this->dof_data.size());
- for (unsigned int i=0; i<this->dof_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; j<i; ++j)
- if (dof_data[i]->dof_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<dhdim,dhspacedim>
- (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<dhdim,dhspacedim>
- (FE_DGQ<dhdim,dhspacedim>(0)));
- }
- return finite_elements;
-}
-
-
-
-template <class DH,
- int patch_dim, int patch_space_dim>
-std::size_t
-DataOut_DoFData<DH,patch_dim,patch_space_dim>::memory_consumption () const
-{
- return (DataOutInterface<patch_dim,patch_space_dim>::memory_consumption () +
- MemoryConsumption::memory_consumption (dofs) +
- MemoryConsumption::memory_consumption (patches));
-}
-
-
-
-/* ---------------------------------------------------------------------- */
-
template <int dim, class DH>
void
// ---------------------------------------------------------------------
-for (VEC : SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
-{
-// codim=0
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<VEC> (const VEC &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<VEC> (const VEC &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<VEC> (const VEC &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const std::string &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const std::vector<std::string> &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
-
-
-// stuff needed for face data
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<VEC> (const VEC &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<VEC> (const VEC &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<VEC> (const VEC &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const std::string &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const std::vector<std::string> &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
-
-
-// things for DataOutRotation
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<VEC> (const VEC &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<VEC> (const VEC &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<VEC> (const VEC &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const std::string &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const std::vector<std::string> &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
- const VEC &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
-
-// codim 1
-
- #if deal_II_dimension < 3
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<VEC> (const VEC &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<VEC> (const VEC &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<VEC> (const VEC &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension+1>::space_dimension> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension+1> &,
- const VEC &,
- const std::string &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension+1> &,
- const VEC &,
- const std::vector<std::string> &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension+1> &,
- const VEC &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension+1>::space_dimension> &);
- #endif
-
-
-
-// codim 2
-
- #if deal_II_dimension == 3
- template void
- DataOut_DoFData<DH<1,3>,1,3>::
- add_data_vector<VEC> (const VEC &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<1,3>,1,3>::
- add_data_vector<VEC> (const VEC &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<1,3>,1,3>::
- add_data_vector<VEC> (const VEC &,
- const DataPostprocessor<DH<1,3>::space_dimension> &);
-
- template void
- DataOut_DoFData<DH<1,3>,1,3>::
- add_data_vector<VEC> (const DH<1,3> &,
- const VEC &,
- const std::string &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<1,3>,1,3>::
- add_data_vector<VEC> (const DH<1,3> &,
- const VEC &,
- const std::vector<std::string> &,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<1,3>,1,3>::
- add_data_vector<VEC> (const DH<1,3> &,
- const VEC &,
- const DataPostprocessor<DH<1,3>::space_dimension> &);
- #endif
-
-}
-
-
-
-for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS)
{
-// codim=0
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<IndexSet> (const IndexSet &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<IndexSet> (const IndexSet &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
- add_data_vector<IndexSet> (const IndexSet &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
-// stuff needed for face data
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<IndexSet> (const IndexSet &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<IndexSet> (const IndexSet &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
- add_data_vector<IndexSet> (const IndexSet &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
-// things for DataOutRotation
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<IndexSet> (const IndexSet &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<IndexSet> (const IndexSet &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
- add_data_vector<IndexSet> (const IndexSet &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
-
-// codim 1
-
- #if deal_II_dimension < 3
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<IndexSet> (const IndexSet &,
- const std::string &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<IndexSet> (const IndexSet &,
- const std::vector<std::string> &,
- const DataVectorType,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
-
- template void
- DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
- add_data_vector<IndexSet> (const IndexSet &,
- const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension+1>::space_dimension> &);
- #endif
-
+ namespace internal \{
+ namespace DataOut \{
+#if deal_II_dimension <= deal_II_space_dimension
+ template struct ParallelData<deal_II_dimension,deal_II_space_dimension>;
+#endif
+ \}
+ \}
}
-
for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
{
template class DataOut_DoFData<DH<deal_II_dimension>,deal_II_dimension>;
template class DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>;
#endif
- #if deal_II_dimension >= 2
- template class DataOut_DoFData<DH<deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>;
- #endif
template class DataOut<deal_II_dimension, DH<deal_II_dimension> >;
#if deal_II_dimension < 3
#endif
#if deal_II_dimension == 3
- template class DataOut_DoFData<DH<1>,1,3>;
- template class DataOut_DoFData<DH<1,3>,1,3>;
template class DataOut<1, DH<1,3> >;
#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<deal_II_dimension,deal_II_space_dimension>;
- template struct ParallelData<deal_II_dimension,deal_II_space_dimension>;
-#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<deal_II_dimension,deal_II_space_dimension>::
- reinit_all_fe_values<dealii::DH<deal_II_dimension,deal_II_space_dimension> >
- (std::vector<std_cxx1x::shared_ptr<DataEntryBase<dealii::DH<deal_II_dimension,deal_II_space_dimension> > > > &dof_data,
- const dealii::Triangulation<deal_II_dimension,deal_II_space_dimension>::cell_iterator &cell,
- const unsigned int face);
-#endif
- \}
- \}
-}
+}
\ No newline at end of file
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/work_stream.h>
+#include <deal.II/base/memory_consumption.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/numerics/data_out.h>
+#include <deal.II/numerics/data_out_dof_data.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/fe/fe.h>
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/hp/dof_handler.h>
+#include <deal.II/hp/fe_values.h>
+#include <deal.II/fe/mapping_q1.h>
+
+#include <sstream>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+namespace internal
+{
+ namespace DataOut
+ {
+ template <int dim, int spacedim>
+ ParallelDataBase<dim,spacedim>::
+ ParallelDataBase (const unsigned int n_datasets,
+ const unsigned int n_subdivisions,
+ const std::vector<unsigned int> &n_postprocessor_outputs,
+ const Mapping<dim,spacedim> &mapping,
+ const std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<dim,spacedim> > > &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<dim>
+ quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
+ n_q_points = quadrature[0].size();
+ x_fe_values.resize(this->finite_elements.size());
+ for (unsigned int i=0; i<this->finite_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; j<i; ++j)
+ if (this->finite_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<dim,spacedim>
+ (this->mapping_collection,
+ *this->finite_elements[i],
+ quadrature,
+ this->update_flags));
+ }
+ }
+ else
+ {
+ dealii::hp::QCollection<dim-1>
+ quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
+ n_q_points = quadrature[0].size();
+ x_fe_face_values.resize(this->finite_elements.size());
+ for (unsigned int i=0; i<this->finite_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; j<i; ++j)
+ if (this->finite_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<dim,spacedim>
+ (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.size(); ++dataset)
+ if (n_postprocessor_outputs[dataset] != 0)
+ postprocessed_values[dataset]
+ .resize(n_q_points,
+ dealii::Vector<double>(n_postprocessor_outputs[dataset]));
+ }
+
+
+
+
+
+ // implement copy constructor to create a thread's own version of
+ // x_fe_values
+ template <int dim, int spacedim>
+ ParallelDataBase<dim,spacedim>::
+ ParallelDataBase (const ParallelDataBase<dim,spacedim> &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<dim>
+ quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
+ x_fe_values.resize(this->finite_elements.size());
+ for (unsigned int i=0; i<this->finite_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; j<i; ++j)
+ if (this->finite_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<dim,spacedim>
+ (this->mapping_collection,
+ *this->finite_elements[i],
+ quadrature,
+ this->update_flags));
+ }
+ }
+ else
+ {
+ dealii::hp::QCollection<dim-1>
+ quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
+ x_fe_face_values.resize(this->finite_elements.size());
+ for (unsigned int i=0; i<this->finite_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; j<i; ++j)
+ if (this->finite_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<dim,spacedim>
+ (this->mapping_collection,
+ *this->finite_elements[i],
+ quadrature,
+ this->update_flags));
+ }
+ }
+ }
+
+
+
+ template <int dim, int spacedim>
+ template <typename DH>
+ void
+ ParallelDataBase<dim,spacedim>::
+ reinit_all_fe_values(std::vector<std_cxx1x::shared_ptr<DataEntryBase<DH> > > &dof_data,
+ const typename dealii::Triangulation<dim,spacedim>::cell_iterator &cell,
+ const unsigned int face)
+ {
+ for (unsigned int dataset=0; dataset<dof_data.size(); ++dataset)
+ {
+ bool duplicate = false;
+ for (unsigned int j=0; j<dataset; ++j)
+ if (finite_elements[dataset].get() == finite_elements[j].get())
+ duplicate = true;
+ if (duplicate == false)
+ {
+ typename DH::active_cell_iterator dh_cell(&cell->get_triangulation(),
+ cell->level(),
+ cell->index(),
+ dof_data[dataset]->dof_handler);
+ if (x_fe_values.empty())
+ {
+ AssertIndexRange(face,
+ GeometryInfo<dim>::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<dim>::faces_per_cell);
+ x_fe_face_values[0]->reinit(cell, face);
+ }
+ else
+ x_fe_values[0]->reinit (cell);
+ }
+ }
+
+
+
+ template <int dim, int spacedim>
+ const FEValuesBase<dim,spacedim> &
+ ParallelDataBase<dim,spacedim>::
+ 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 <int dim, int spacedim>
+ void
+ ParallelDataBase<dim,spacedim>::
+ 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<patch_values_system.size(); ++k)
+ {
+ patch_values_system[k].reinit(n_components);
+ patch_gradients_system[k].resize(n_components);
+ patch_hessians_system[k].resize(n_components);
+ }
+ }
+
+
+
+
+ /**
+ * In a WorkStream context, use this function to append the patch computed
+ * by the parallel stage to the array of patches.
+ */
+ template <int dim, int spacedim>
+ void
+ append_patch_to_list (const DataOutBase::Patch<dim,spacedim> &patch,
+ std::vector<DataOutBase::Patch<dim,spacedim> > &patches)
+ {
+ patches.push_back (patch);
+ patches.back().patch_index = patches.size()-1;
+ }
+ }
+}
+
+namespace internal
+{
+ namespace DataOut
+ {
+ template <class DH>
+ DataEntryBase<DH>::DataEntryBase (const DH *dofs,
+ const std::vector<std::string> &names_in,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
+ :
+ dof_handler (dofs, typeid(dealii::DataOut_DoFData<DH,DH::dimension,DH::space_dimension>).name()),
+ names(names_in),
+ data_component_interpretation (data_component_interpretation),
+ postprocessor(0, typeid(*this).name()),
+ n_output_variables(names.size())
+ {
+ Assert (names.size() == data_component_interpretation.size(),
+ ExcDimensionMismatch(data_component_interpretation.size(),
+ names.size()));
+
+ // check that the names use only allowed characters
+ for (unsigned int i=0; i<names.size(); ++i)
+ Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789_<>()") == std::string::npos,
+ typename dealii::DataOut<DH::dimension>::
+ ExcInvalidCharacter (names[i],
+ names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789_<>()")));
+ }
+
+
+
+ template <class DH>
+ DataEntryBase<DH>::DataEntryBase (const DH *dofs,
+ const DataPostprocessor<DH::space_dimension> *data_postprocessor)
+ :
+ dof_handler (dofs, typeid(dealii::DataOut_DoFData<DH,DH::dimension,DH::space_dimension>).name()),
+ names(data_postprocessor->get_names()),
+ data_component_interpretation (data_postprocessor->get_data_component_interpretation()),
+ postprocessor(data_postprocessor, typeid(*this).name()),
+ n_output_variables(names.size())
+ {
+ Assert (data_postprocessor->get_names().size()
+ ==
+ data_postprocessor->get_data_component_interpretation().size(),
+ ExcDimensionMismatch (data_postprocessor->get_names().size(),
+ data_postprocessor->get_data_component_interpretation().size()));
+
+ // check that the names use only allowed characters
+ for (unsigned int i=0; i<names.size(); ++i)
+ Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789_<>()") == std::string::npos,
+ typename dealii::DataOut<DH::dimension>::
+ ExcInvalidCharacter (names[i],
+ names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789_<>()")));
+ }
+
+
+
+ template <class DH>
+ DataEntryBase<DH>::~DataEntryBase ()
+ {}
+
+
+
+ /**
+ * Class that stores a pointer to a vector of type equal to the template
+ * argument, and provides the functions to extract data from it.
+ *
+ * @author Wolfgang Bangerth, 2004
+ */
+ template <class DH, typename VectorType>
+ class DataEntry : public DataEntryBase<DH>
+ {
+ 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.
+ */
+ DataEntry (const DH *dofs,
+ const VectorType *data,
+ const std::vector<std::string> &names,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &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.
+ */
+ DataEntry (const DH *dofs,
+ const VectorType *data,
+ const DataPostprocessor<DH::space_dimension> *data_postprocessor);
+
+ /**
+ * Assuming that the stored vector is a cell vector, extract the given
+ * element from it.
+ */
+ virtual
+ double
+ 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.
+ */
+ virtual
+ void
+ get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<double> &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.
+ */
+ virtual
+ void
+ get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<dealii::Vector<double> > &patch_values_system) const;
+
+ /**
+ * Given a FEValuesBase object, extract the gradients on the present
+ * cell from the vector we actually store.
+ */
+ virtual
+ void
+ get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<Tensor<1,DH::space_dimension> > &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.
+ */
+ virtual
+ void
+ get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<std::vector<Tensor<1,DH::space_dimension> > > &patch_gradients_system) const;
+
+ /**
+ * Given a FEValuesBase object, extract the second derivatives on the
+ * present cell from the vector we actually store.
+ */
+ virtual
+ void
+ get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<Tensor<2,DH::space_dimension> > &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.
+ */
+ virtual
+ void
+ get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<std::vector< Tensor<2,DH::space_dimension> > > &patch_hessians_system) const;
+
+ /**
+ * Clear all references to the vectors.
+ */
+ virtual void clear ();
+
+ /**
+ * 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.
+ */
+ const VectorType *vector;
+ };
+
+
+
+ template <class DH, class VectorType>
+ DataEntry<DH,VectorType>::
+ DataEntry (const DH *dofs,
+ const VectorType *data,
+ const std::vector<std::string> &names,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
+ :
+ DataEntryBase<DH> (dofs, names, data_component_interpretation),
+ vector (data)
+ {}
+
+
+
+ template <class DH, class VectorType>
+ DataEntry<DH,VectorType>::
+ DataEntry (const DH *dofs,
+ const VectorType *data,
+ const DataPostprocessor<DH::space_dimension> *data_postprocessor)
+ :
+ DataEntryBase<DH> (dofs, data_postprocessor),
+ vector (data)
+ {}
+
+
+ namespace
+ {
+ template <class VectorType>
+ double
+ get_vector_element (const VectorType &vector,
+ const unsigned int cell_number)
+ {
+ return vector[cell_number];
+ }
+
+
+ double
+ get_vector_element (const IndexSet &is,
+ const unsigned int cell_number)
+ {
+ return (is.is_element(cell_number) ? 1 : 0);
+ }
+ }
+
+
+
+ template <class DH, class VectorType>
+ double
+ DataEntry<DH,VectorType>::
+ get_cell_data_value (const unsigned int cell_number) const
+ {
+ return get_vector_element(*vector, cell_number);
+ }
+
+
+
+ template <class DH, class VectorType>
+ void
+ DataEntry<DH,VectorType>::
+ get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<dealii::Vector<double> > &patch_values_system) const
+ {
+ fe_patch_values.get_function_values (*vector, patch_values_system);
+ }
+
+
+
+ template <class DH, typename VectorType>
+ void
+ DataEntry<DH,VectorType>::
+ get_function_values (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<double> &patch_values) const
+ {
+ fe_patch_values.get_function_values (*vector, patch_values);
+ }
+
+
+
+ template <class DH, class VectorType>
+ void
+ DataEntry<DH,VectorType>::
+ get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<std::vector<Tensor<1,DH::space_dimension> > > &patch_gradients_system) const
+ {
+ fe_patch_values.get_function_gradients (*vector, patch_gradients_system);
+ }
+
+
+
+ template <class DH, typename VectorType>
+ void
+ DataEntry<DH,VectorType>::
+ get_function_gradients (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<Tensor<1,DH::space_dimension> > &patch_gradients) const
+ {
+ fe_patch_values.get_function_gradients (*vector, patch_gradients);
+ }
+
+
+
+ template <class DH, class VectorType>
+ void
+ DataEntry<DH,VectorType>::
+ get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<std::vector<Tensor<2,DH::space_dimension> > > &patch_hessians_system) const
+ {
+ fe_patch_values.get_function_hessians (*vector, patch_hessians_system);
+ }
+
+
+
+ template <class DH, typename VectorType>
+ void
+ DataEntry<DH,VectorType>::
+ get_function_hessians (const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values,
+ std::vector<Tensor<2,DH::space_dimension> > &patch_hessians) const
+ {
+ fe_patch_values.get_function_hessians (*vector, patch_hessians);
+ }
+
+
+
+ template <class DH, typename VectorType>
+ std::size_t
+ DataEntry<DH,VectorType>::memory_consumption () const
+ {
+ return (sizeof (vector) +
+ MemoryConsumption::memory_consumption (this->names));
+ }
+
+
+
+ template <class DH, class VectorType>
+ void
+ DataEntry<DH,VectorType>::clear ()
+ {
+ vector = 0;
+ this->dof_handler = 0;
+ }
+ }
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::DataOut_DoFData ()
+ :
+ triangulation(0,typeid(*this).name()),
+ dofs(0,typeid(*this).name())
+{}
+
+
+
+template <class DH, int patch_dim, int patch_space_dim>
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::~DataOut_DoFData ()
+{
+ clear ();
+}
+
+
+
+template <class DH, int patch_dim, int patch_space_dim>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+attach_dof_handler (const DH &d)
+{
+ Assert (dof_data.size() == 0, ExcOldDataStillPresent());
+ Assert (cell_data.size() == 0, ExcOldDataStillPresent());
+
+ triangulation = SmartPointer<const Triangulation<DH::dimension,DH::space_dimension> >(&d.get_tria(), typeid(*this).name());
+ dofs = SmartPointer<const DH>(&d, typeid(*this).name());
+}
+
+
+
+template <class DH, int patch_dim, int patch_space_dim>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+attach_triangulation (const Triangulation<DH::dimension,DH::space_dimension> &tria)
+{
+ Assert (dof_data.size() == 0, ExcOldDataStillPresent());
+ Assert (cell_data.size() == 0, ExcOldDataStillPresent());
+
+ triangulation = SmartPointer<const Triangulation<DH::dimension,DH::space_dimension> >(&tria, typeid(*this).name());
+}
+
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+template <class VECTOR>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+add_data_vector (const VECTOR &vec,
+ const std::string &name,
+ const DataVectorType type,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
+{
+ Assert (triangulation != 0, ExcNoTriangulationSelected ());
+ const unsigned int n_components =
+ dofs != 0 ? dofs->get_fe().n_components () : 1;
+
+ std::vector<std::string> names;
+ // if only one component or vector is cell vector: we only need one name
+ if ((n_components == 1) ||
+ (vec.size() == triangulation->n_active_cells()))
+ {
+ names.resize (1, name);
+ }
+ else
+ // otherwise append _i to the given name
+ {
+ names.resize (n_components);
+ for (unsigned int i=0; i<n_components; ++i)
+ {
+ std::ostringstream namebuf;
+ namebuf << '_' << i;
+ names[i] = name + namebuf.str();
+ }
+ }
+
+ add_data_vector (vec, names, type, data_component_interpretation);
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+template <class VECTOR>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+add_data_vector (const VECTOR &vec,
+ const std::vector<std::string> &names,
+ const DataVectorType type,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation_)
+{
+ Assert (triangulation != 0, ExcNoTriangulationSelected ());
+
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &
+ data_component_interpretation
+ = (data_component_interpretation_.size() != 0
+ ?
+ data_component_interpretation_
+ :
+ std::vector<DataComponentInterpretation::DataComponentInterpretation>
+ (names.size(), DataComponentInterpretation::component_is_scalar));
+
+ // either cell data and one name,
+ // or dof data and n_components names
+ DataVectorType actual_type = type;
+ if (type == type_automatic)
+ {
+ if (vec.size() == triangulation->n_active_cells())
+ actual_type = type_cell_data;
+ else
+ actual_type = type_dof_data;
+ }
+
+ switch (actual_type)
+ {
+ case type_cell_data:
+ 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(),
+ 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...
+ Assert (false, ExcInternalError());
+ }
+
+ internal::DataOut::DataEntryBase<DH> *new_entry
+ = new internal::DataOut::DataEntry<DH,VECTOR>(dofs, &vec, names,
+ data_component_interpretation);
+ if (actual_type == type_dof_data)
+ dof_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
+ else
+ cell_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+template <class VECTOR>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+add_data_vector (const VECTOR &vec,
+ const DataPostprocessor<DH::space_dimension> &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
+
+ Assert (dofs != 0, ExcNoDoFHandlerSelected ());
+
+ Assert (vec.size() == dofs->n_dofs(),
+ ExcInvalidVectorSize (vec.size(),
+ dofs->n_dofs(),
+ dofs->get_tria().n_active_cells()));
+
+ internal::DataOut::DataEntryBase<DH> *new_entry
+ = new internal::DataOut::DataEntry<DH,VECTOR>(dofs, &vec, &data_postprocessor);
+ dof_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+template <class VECTOR>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+add_data_vector (const DH &dof_handler,
+ const VECTOR &vec,
+ const DataPostprocessor<DH::space_dimension> &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<DH> *new_entry
+ = new internal::DataOut::DataEntry<DH,VECTOR>(&dof_handler, &vec, &data_postprocessor);
+ dof_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+template <class VECTOR>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+add_data_vector (const DH &dof_handler,
+ const VECTOR &data,
+ const std::string &name,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
+{
+ const unsigned int n_components = dof_handler.get_fe().n_components ();
+
+ std::vector<std::string> 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<n_components; ++i)
+ {
+ std::ostringstream namebuf;
+ namebuf << '_' << i;
+ names[i] = name + namebuf.str();
+ }
+ }
+
+ add_data_vector (dof_handler, data, names, data_component_interpretation);
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+template <class VECTOR>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+add_data_vector (const DH &dof_handler,
+ const VECTOR &data,
+ const std::vector<std::string> &names,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &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<const Triangulation<DH::dimension,DH::space_dimension> >(&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<DataComponentInterpretation::DataComponentInterpretation> &
+ data_component_interpretation
+ = (data_component_interpretation_.size() != 0
+ ?
+ data_component_interpretation_
+ :
+ std::vector<DataComponentInterpretation::DataComponentInterpretation>
+ (names.size(), DataComponentInterpretation::component_is_scalar));
+
+ internal::DataOut::DataEntryBase<DH> *new_entry
+ = new internal::DataOut::DataEntry<DH,VECTOR>(&dof_handler, &data, names,
+ data_component_interpretation);
+ dof_data.push_back (std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> >(new_entry));
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+void DataOut_DoFData<DH,patch_dim,patch_space_dim>::clear_data_vectors ()
+{
+ dof_data.erase (dof_data.begin(), dof_data.end());
+ cell_data.erase (cell_data.begin(), cell_data.end());
+
+ // delete patches
+ std::vector<Patch> dummy;
+ patches.swap (dummy);
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+clear_input_data_references ()
+{
+ for (unsigned int i=0; i<dof_data.size(); ++i)
+ dof_data[i]->clear ();
+
+ for (unsigned int i=0; i<cell_data.size(); ++i)
+ cell_data[i]->clear ();
+
+ if (dofs != 0)
+ dofs = 0;
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+void
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::clear ()
+{
+ dof_data.erase (dof_data.begin(), dof_data.end());
+ cell_data.erase (cell_data.begin(), cell_data.end());
+
+ if (dofs != 0)
+ dofs = 0;
+
+ // delete patches
+ std::vector<Patch> dummy;
+ patches.swap (dummy);
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+std::vector<std::string>
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::
+get_dataset_names () const
+{
+ std::vector<std::string> names;
+ // collect the names of dof
+ // and cell data
+ typedef
+ typename std::vector<std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> > >::const_iterator
+ data_iterator;
+
+ for (data_iterator d=dof_data.begin();
+ d!=dof_data.end(); ++d)
+ for (unsigned int i=0; i<(*d)->names.size(); ++i)
+ names.push_back ((*d)->names[i]);
+ for (data_iterator d=cell_data.begin(); d!=cell_data.end(); ++d)
+ {
+ Assert ((*d)->names.size() == 1, ExcInternalError());
+ names.push_back ((*d)->names[0]);
+ }
+
+ return names;
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::get_vector_data_ranges () const
+{
+ std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >
+ ranges;
+
+ // collect the ranges of dof
+ // and cell data
+ typedef
+ typename std::vector<std_cxx1x::shared_ptr<internal::DataOut::DataEntryBase<DH> > >::const_iterator
+ data_iterator;
+
+ unsigned int output_component = 0;
+ for (data_iterator d=dof_data.begin();
+ d!=dof_data.end(); ++d)
+ for (unsigned int i=0; i<(*d)->n_output_variables;
+ ++i, ++output_component)
+ // see what kind of data we have
+ // here. note that for the purpose of
+ // the current function all we care
+ // about is vector data
+ if ((*d)->data_component_interpretation[i] ==
+ DataComponentInterpretation::component_is_part_of_vector)
+ {
+ // ensure that there is a
+ // continuous number of next
+ // space_dim components that all
+ // deal with vectors
+ Assert (i+patch_space_dim <=
+ (*d)->n_output_variables,
+ ExcInvalidVectorDeclaration (i,
+ (*d)->names[i]));
+ for (unsigned int dd=1; dd<patch_space_dim; ++dd)
+ Assert ((*d)->data_component_interpretation[i+dd]
+ ==
+ DataComponentInterpretation::component_is_part_of_vector,
+ ExcInvalidVectorDeclaration (i,
+ (*d)->names[i]));
+
+ // all seems alright, so figure out
+ // whether there is a common name
+ // to these components. if not,
+ // leave the name empty and let the
+ // output format writer decide what
+ // to do here
+ std::string name = (*d)->names[i];
+ for (unsigned int dd=1; dd<patch_space_dim; ++dd)
+ if (name != (*d)->names[i+dd])
+ {
+ name = "";
+ break;
+ }
+
+ // finally add a corresponding
+ // range
+ std_cxx1x::tuple<unsigned int, unsigned int, std::string>
+ range (output_component,
+ output_component+patch_space_dim-1,
+ name);
+
+ ranges.push_back (range);
+
+ // increase the 'component' counter
+ // by the appropriate amount, same
+ // for 'i', since we have already
+ // dealt with all these components
+ output_component += patch_space_dim-1;
+ i += patch_space_dim-1;
+ }
+
+ // note that we do not have to traverse the
+ // list of cell data here because cell data
+ // is one value per (logical) cell and
+ // therefore cannot be a vector
+
+ // as a final check, the 'component'
+ // counter should be at the total number of
+ // components added up now
+#ifdef DEBUG
+ unsigned int n_output_components = 0;
+ for (data_iterator d=dof_data.begin();
+ d!=dof_data.end(); ++d)
+ n_output_components += (*d)->n_output_variables;
+ Assert (output_component == n_output_components,
+ ExcInternalError());
+#endif
+
+ return ranges;
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+const std::vector< dealii::DataOutBase::Patch<patch_dim, patch_space_dim> > &
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::get_patches () const
+{
+ return patches;
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<DH::dimension,DH::space_dimension> > >
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::get_finite_elements() const
+{
+ const unsigned int dhdim = DH::dimension;
+ const unsigned int dhspacedim = DH::space_dimension;
+ std::vector<std_cxx1x::shared_ptr<dealii::hp::FECollection<dhdim,dhspacedim> > >
+ finite_elements(this->dof_data.size());
+ for (unsigned int i=0; i<this->dof_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; j<i; ++j)
+ if (dof_data[i]->dof_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<dhdim,dhspacedim>
+ (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<dhdim,dhspacedim>
+ (FE_DGQ<dhdim,dhspacedim>(0)));
+ }
+ return finite_elements;
+}
+
+
+
+template <class DH,
+ int patch_dim, int patch_space_dim>
+std::size_t
+DataOut_DoFData<DH,patch_dim,patch_space_dim>::memory_consumption () const
+{
+ return (DataOutInterface<patch_dim,patch_space_dim>::memory_consumption () +
+ MemoryConsumption::memory_consumption (dofs) +
+ MemoryConsumption::memory_consumption (patches));
+}
+
+
+
+// explicit instantiations
+#include "data_out_dof_data.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+
+for (VEC : SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
+{
+// codim=0
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<VEC> (const VEC &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<VEC> (const VEC &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<VEC> (const VEC &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const std::string &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const std::vector<std::string> &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+
+
+// stuff needed for face data
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<VEC> (const VEC &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<VEC> (const VEC &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<VEC> (const VEC &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const std::string &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const std::vector<std::string> &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+
+
+// things for DataOutRotation
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<VEC> (const VEC &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<VEC> (const VEC &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<VEC> (const VEC &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const std::string &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const std::vector<std::string> &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const VEC &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+
+
+// codim 1
+
+ #if deal_II_dimension < 3
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<VEC> (const VEC &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<VEC> (const VEC &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<VEC> (const VEC &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension+1>::space_dimension> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension+1> &,
+ const VEC &,
+ const std::string &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension+1> &,
+ const VEC &,
+ const std::vector<std::string> &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension+1> &,
+ const VEC &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension+1>::space_dimension> &);
+ #endif
+
+
+
+// codim 2
+
+ #if deal_II_dimension == 3
+ template void
+ DataOut_DoFData<DH<1,3>,1,3>::
+ add_data_vector<VEC> (const VEC &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<1,3>,1,3>::
+ add_data_vector<VEC> (const VEC &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<1,3>,1,3>::
+ add_data_vector<VEC> (const VEC &,
+ const DataPostprocessor<DH<1,3>::space_dimension> &);
+
+ template void
+ DataOut_DoFData<DH<1,3>,1,3>::
+ add_data_vector<VEC> (const DH<1,3> &,
+ const VEC &,
+ const std::string &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<1,3>,1,3>::
+ add_data_vector<VEC> (const DH<1,3> &,
+ const VEC &,
+ const std::vector<std::string> &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<1,3>,1,3>::
+ add_data_vector<VEC> (const DH<1,3> &,
+ const VEC &,
+ const DataPostprocessor<DH<1,3>::space_dimension> &);
+ #endif
+
+}
+
+
+
+for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
+{
+// codim=0
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<IndexSet> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const IndexSet &,
+ const std::string &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<IndexSet> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const IndexSet &,
+ const std::vector<std::string> &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+
+
+// stuff needed for face data
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<IndexSet> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const IndexSet &,
+ const std::string &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>::
+ add_data_vector<IndexSet> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const IndexSet &,
+ const std::vector<std::string> &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+// things for DataOutRotation
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<IndexSet> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const IndexSet &,
+ const std::string &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension+1,deal_II_dimension+1>::
+ add_data_vector<IndexSet> (const DH<deal_II_dimension,deal_II_dimension> &,
+ const IndexSet &,
+ const std::vector<std::string> &,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+// codim 1
+
+ #if deal_II_dimension < 3
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const std::string &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const std::vector<std::string> &,
+ const DataVectorType,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &);
+
+ template void
+ DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
+ add_data_vector<IndexSet> (const IndexSet &,
+ const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension+1>::space_dimension> &);
+ #endif
+
+}
+
+
+
+for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
+{
+ template class DataOut_DoFData<DH<deal_II_dimension>,deal_II_dimension>;
+ template class DataOut_DoFData<DH<deal_II_dimension>,deal_II_dimension+1>;
+
+ #if deal_II_dimension < 3
+ template class DataOut_DoFData<DH<deal_II_dimension>,deal_II_dimension,deal_II_dimension+1>;
+ template class DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>;
+ #endif
+
+ #if deal_II_dimension >= 2
+ template class DataOut_DoFData<DH<deal_II_dimension>,deal_II_dimension-1,deal_II_dimension>;
+ #endif
+
+ #if deal_II_dimension == 3
+ template class DataOut_DoFData<DH<1>,1,3>;
+ template class DataOut_DoFData<DH<1,3>,1,3>;
+ #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<deal_II_dimension,deal_II_space_dimension>;
+#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<deal_II_dimension,deal_II_space_dimension>::
+ reinit_all_fe_values<dealii::DH<deal_II_dimension,deal_II_space_dimension> >
+ (std::vector<std_cxx1x::shared_ptr<DataEntryBase<dealii::DH<deal_II_dimension,deal_II_space_dimension> > > > &dof_data,
+ const dealii::Triangulation<deal_II_dimension,deal_II_space_dimension>::cell_iterator &cell,
+ const unsigned int face);
+#endif
+ \}
+ \}
+}
namespace
{
- inline
- double sqr (const double x)
- {
- return x*x;
- }
-
-
template <typename CellIterator>
inline
void advance_by_n (CellIterator &cell,
const unsigned int n)
{
- // store a pointer to the end
- // iterator, since we can't get at
- // it any more once cell is already
- // the end iterator (in that case
- // dereferencing cell-> triggers an
- // assertion)
+ // store a pointer to the end iterator, since we can't get at it any more
+ // once cell is already the end iterator (in that case dereferencing
+ // cell-> triggers an assertion)
const CellIterator endc = cell->get_dof_handler().end();
for (unsigned int t=0; ((t<n) && (cell!=endc)); ++t, ++cell)
;
namespace
{
/**
- * All small temporary data
- * objects that are needed once
- * per thread by the several
- * functions of the error
- * estimator are gathered in this
- * struct. The reason for this
- * structure is mainly that we
- * have a number of functions
- * that operate on cells or faces
- * and need a number of small
- * temporary data objects. Since
- * these functions may run in
- * parallel, we cannot make these
- * objects member variables of
- * the enclosing class. On the
- * other hand, declaring them
- * locally in each of these
- * functions would require their
- * reallocating every time we
- * visit the next cell or face,
- * which we found can take a
- * significant amount of time if
- * it happens often even in the
- * single threaded case (10-20
- * per cent in our measurements);
- * however, most importantly,
- * memory allocation requires
- * synchronisation in
- * multithreaded mode. While that
- * is done by the C++ library and
- * has not to be handcoded, it
- * nevertheless seriously damages
- * the ability to efficiently run
- * the functions of this class in
- * parallel, since they are quite
- * often blocked by these
- * synchronisation points,
- * slowing everything down by a
- * factor of two or three.
+ * All small temporary data objects that are needed once per thread by the
+ * several functions of the error estimator are gathered in this
+ * struct. The reason for this structure is mainly that we have a number
+ * of functions that operate on cells or faces and need a number of small
+ * temporary data objects. Since these functions may run in parallel, we
+ * cannot make these objects member variables of the enclosing class. On
+ * the other hand, declaring them locally in each of these functions would
+ * require their reallocating every time we visit the next cell or face,
+ * which we found can take a significant amount of time if it happens
+ * often even in the single threaded case (10-20 per cent in our
+ * measurements); however, most importantly, memory allocation requires
+ * synchronisation in multithreaded mode. While that is done by the C++
+ * library and has not to be handcoded, it nevertheless seriously damages
+ * the ability to efficiently run the functions of this class in parallel,
+ * since they are quite often blocked by these synchronisation points,
+ * slowing everything down by a factor of two or three.
*
- * Thus, every thread gets an
- * instance of this class to work
- * with and needs not allocate
- * memory itself, or synchronise
- * with other threads.
+ * Thus, every thread gets an instance of this class to work with and
+ * needs not allocate memory itself, or synchronise with other threads.
*
- * The sizes of the arrays are
- * initialized with the maximal number of
- * entries necessary for the hp
- * case. Within the loop over individual
- * cells, we then resize the arrays as
- * necessary. Since for std::vector
- * resizing to a smaller size doesn't
- * imply memory allocation, this is fast.
+ * The sizes of the arrays are initialized with the maximal number of
+ * entries necessary for the hp case. Within the loop over individual
+ * cells, we then resize the arrays as necessary. Since for std::vector
+ * resizing to a smaller size doesn't imply memory allocation, this is
+ * fast.
*/
template <class DH>
struct ParallelData
const dealii::hp::FECollection<dim,spacedim> finite_element;
/**
- * The quadrature formulas to be used for
- * the faces.
+ * The quadrature formulas to be used for the faces.
*/
const dealii::hp::QCollection<dim-1> face_quadratures;
/**
- * FEFaceValues objects to integrate over
- * the faces of the current and
+ * FEFaceValues objects to integrate over the faces of the current and
* potentially of neighbor cells.
*/
dealii::hp::FEFaceValues<dim,spacedim> fe_face_values_cell;
dealii::hp::FESubfaceValues<dim,spacedim> fe_subface_values;
/**
- * A vector to store the jump
- * of the normal vectors in
- * the quadrature points for
- * each of the solution
- * vectors (i.e. a temporary
- * value). This vector is not
- * allocated inside the
- * functions that use it, but
- * rather globally, since
- * memory allocation is slow,
- * in particular in presence
- * of multiple threads where
- * synchronisation makes
- * things even slower.
+ * A vector to store the jump of the normal vectors in the quadrature
+ * points for each of the solution vectors (i.e. a temporary
+ * value). This vector is not allocated inside the functions that use
+ * it, but rather globally, since memory allocation is slow, in
+ * particular in presence of multiple threads where synchronisation
+ * makes things even slower.
*/
std::vector<std::vector<std::vector<double> > > phi;
/**
- * A vector for the gradients of
- * the finite element function
- * on one cell
+ * A vector for the gradients of the finite element function on one cell
*
- * Let psi be a short name
- * for <tt>a grad u_h</tt>, where
- * the third index be the
- * component of the finite
- * element, and the second
- * index the number of the
- * quadrature point. The
- * first index denotes the
- * index of the solution
- * vector.
+ * Let psi be a short name for <tt>a grad u_h</tt>, where the third
+ * index be the component of the finite element, and the second index
+ * the number of the quadrature point. The first index denotes the index
+ * of the solution vector.
*/
std::vector<std::vector<std::vector<Tensor<1,spacedim> > > > psi;
std::vector<std::vector<std::vector<Tensor<1,spacedim> > > > neighbor_psi;
/**
- * The normal vectors of the finite
- * element function on one face
+ * The normal vectors of the finite element function on one face
*/
std::vector<Point<spacedim> > normal_vectors;
/**
- * Two arrays needed for the
- * values of coefficients in
- * the jumps, if they are
- * given.
+ * Two arrays needed for the values of coefficients in the jumps, if
+ * they are given.
*/
std::vector<double> coefficient_values1;
std::vector<dealii::Vector<double> > coefficient_values;
/**
- * Array for the products of
- * Jacobian determinants and
- * weights of quadraturs
- * points.
+ * Array for the products of Jacobian determinants and weights of
+ * quadraturs points.
*/
std::vector<double> JxW_values;
/**
- * The subdomain id we are to care
- * for.
+ * The subdomain id we are to care for.
*/
const types::subdomain_id subdomain_id;
/**
- * The material id we are to care
- * for.
+ * The material id we are to care for.
*/
const types::material_id material_id;
/**
- * Some more references to input data to
- * the KellyErrorEstimator::estimate()
- * function.
+ * Some more references to input data to the
+ * KellyErrorEstimator::estimate() function.
*/
const typename FunctionMap<spacedim>::type *neumann_bc;
const ComponentMask component_mask;
const Function<spacedim> *coefficients);
/**
- * Resize the arrays so that they fit the
- * number of quadrature points associated
- * with the given finite element index
- * into the hp collections.
+ * Resize the arrays so that they fit the number of quadrature points
+ * associated with the given finite element index into the hp
+ * collections.
*/
void resize (const unsigned int active_fe_index);
};
/**
- * Copy data from the
- * local_face_integrals map of a single
- * ParallelData object into a global such
- * map. This is the copier stage of a
- * WorkStream pipeline.
+ * Copy data from the local_face_integrals map of a single ParallelData
+ * object into a global such map. This is the copier stage of a WorkStream
+ * pipeline.
*/
template <class DH>
void
std::map<typename DH::face_iterator,std::vector<double> > &face_integrals)
{
- // now copy locally computed elements
- // into the global map
+ // now copy locally computed elements into the global map
for (typename std::map<typename DH::face_iterator,std::vector<double> >::const_iterator
p=local_face_integrals.begin();
p!=local_face_integrals.end();
++p)
{
- // double check that the
- // element does not already
- // exists in the global map
+ // double check that the element does not already exists in the
+ // global map
Assert (face_integrals.find (p->first) == face_integrals.end(),
ExcInternalError());
/**
- * Actually do the computation on
- * a face which has no hanging
- * nodes (it is regular), i.e.
- * either on the other side there
- * is nirvana (face is at
- * boundary), or the other side's
- * refinement level is the same
- * as that of this side, then
- * handle the integration of
- * these both cases together.
+ * Actually do the computation based on the evaluated gradients in
+ * ParallelData.
*/
- template <typename InputVector, class DH>
- void
- integrate_over_regular_face (const std::vector<const InputVector *> &solutions,
- ParallelData<DH> ¶llel_data,
- std::map<typename DH::face_iterator,std::vector<double> > &local_face_integrals,
- const typename DH::active_cell_iterator &cell,
- const unsigned int face_no,
- dealii::hp::FEFaceValues<DH::dimension, DH::space_dimension> &fe_face_values_cell,
- dealii::hp::FEFaceValues<DH::dimension, DH::space_dimension> &fe_face_values_neighbor)
+ template <class DH>
+ std::vector<double>
+ integrate_over_face (ParallelData<DH> ¶llel_data,
+ const typename DH::face_iterator &face,
+ dealii::hp::FEFaceValues<DH::dimension, DH::space_dimension> &fe_face_values_cell)
{
- const unsigned int dim = DH::dimension;
-
- const typename DH::face_iterator face = cell->face(face_no);
- const unsigned int n_q_points = parallel_data.face_quadratures[cell->active_fe_index()].size(),
+ const unsigned int n_q_points = parallel_data.psi[0].size(),
n_components = parallel_data.finite_element.n_components(),
- n_solution_vectors = solutions.size();
-
-
- // initialize data of the restriction
- // of this cell to the present face
- fe_face_values_cell.reinit (cell, face_no,
- cell->active_fe_index());
+ n_solution_vectors = parallel_data.psi.size();
- // get gradients of the finite element
- // function on this cell
- for (unsigned int n=0; n<n_solution_vectors; ++n)
- fe_face_values_cell.get_present_fe_values()
- .get_function_gradients (*solutions[n], parallel_data.psi[n]);
-
- // now compute over the other side of
- // the face
if (face->at_boundary() == false)
- // internal face; integrate jump
- // of gradient across this face
{
- Assert (cell->neighbor(face_no).state() == IteratorState::valid,
- ExcInternalError());
-
- const typename DH::active_cell_iterator neighbor = cell->neighbor(face_no);
-
- // find which number the
- // current face has relative to
- // the neighboring cell
- const unsigned int neighbor_neighbor
- = cell->neighbor_of_neighbor (face_no);
- Assert (neighbor_neighbor<GeometryInfo<dim>::faces_per_cell,
- ExcInternalError());
-
- // get restriction of finite element
- // function of @p{neighbor} to the
- // common face. in the hp case, use the
- // quadrature formula that matches the
- // one we would use for the present
- // cell
- fe_face_values_neighbor.reinit (neighbor, neighbor_neighbor,
- cell->active_fe_index());
-
- // get gradients on neighbor cell
+ // compute the jump in the gradients
for (unsigned int n=0; n<n_solution_vectors; ++n)
- {
- fe_face_values_neighbor.get_present_fe_values()
- .get_function_gradients (*solutions[n],
- parallel_data.neighbor_psi[n]);
-
- // compute the jump in the gradients
- for (unsigned int component=0; component<n_components; ++component)
- for (unsigned int p=0; p<n_q_points; ++p)
- parallel_data.psi[n][p][component] -= parallel_data.neighbor_psi[n][p][component];
- }
+ for (unsigned int component=0; component<n_components; ++component)
+ for (unsigned int p=0; p<n_q_points; ++p)
+ parallel_data.psi[n][p][component] -= parallel_data.neighbor_psi[n][p][component];
}
-
// now psi contains the following:
// - for an internal face, psi=[grad u]
- // - for a neumann boundary face,
- // psi=grad u
- // each component being the
- // mentioned value at one of the
- // quadrature points
-
- // next we have to multiply this with
- // the normal vector. Since we have
- // taken the difference of gradients
- // for internal faces, we may chose
- // the normal vector of one cell,
- // taking that of the neighbor
- // would only change the sign. We take
- // the outward normal.
+ // - for a neumann boundary face, psi=grad u
+ // each component being the mentioned value at one of the quadrature
+ // points
+
+ // next we have to multiply this with the normal vector. Since we have
+ // taken the difference of gradients for internal faces, we may chose
+ // the normal vector of one cell, taking that of the neighbor would only
+ // change the sign. We take the outward normal.
parallel_data.normal_vectors =
fe_face_values_cell.get_present_fe_values().get_normal_vectors();
= (parallel_data.psi[n][point][component] *
parallel_data.normal_vectors[point]);
- // if a coefficient was given: use that
- // to scale the jump in the gradient
+ // if a coefficient was given: use that to scale the jump in the
+ // gradient
if (parallel_data.coefficients != 0)
{
// scalar coefficient
if (parallel_data.coefficients->n_components == 1)
{
-
parallel_data.coefficients
->value_list (fe_face_values_cell.get_present_fe_values()
.get_quadrature_points(),
if (face->at_boundary() == true)
- // neumann boundary face. compute
- // difference between normal
- // derivative and boundary function
+ // neumann boundary face. compute difference between normal derivative
+ // and boundary function
{
const types::boundary_id boundary_indicator = face->boundary_indicator();
Assert (parallel_data.neumann_bc->find(boundary_indicator) !=
parallel_data.neumann_bc->end(),
ExcInternalError ());
- // get the values of the boundary
- // function at the quadrature
- // points
+ // get the values of the boundary function at the quadrature points
if (n_components == 1)
{
std::vector<double> g(n_q_points);
// now phi contains the following:
// - for an internal face, phi=[a du/dn]
- // - for a neumann boundary face,
- // phi=a du/dn-g
- // each component being the
- // mentioned value at one of the
- // quadrature points
+ // - for a neumann boundary face, phi=a du/dn-g
+ // each component being the mentioned value at one of the quadrature
+ // points
parallel_data.JxW_values
= fe_face_values_cell.get_present_fe_values().get_JxW_values();
- // take the square of the phi[i]
- // for integration, and sum up
+ // take the square of the phi[i] for integration, and sum up
std::vector<double> face_integral (n_solution_vectors, 0);
for (unsigned int n=0; n<n_solution_vectors; ++n)
for (unsigned int component=0; component<n_components; ++component)
if (parallel_data.component_mask[component] == true)
for (unsigned int p=0; p<n_q_points; ++p)
- face_integral[n] += dealii::sqr(parallel_data.phi[n][p][component]) *
+ face_integral[n] += Utilities::fixed_power<2>(parallel_data.phi[n][p][component]) *
parallel_data.JxW_values[p];
- local_face_integrals[face] = face_integral;
+ return face_integral;
+ }
+
+
+
+ /**
+ * Actually do the computation on a face which has no hanging nodes (it is
+ * regular), i.e. either on the other side there is nirvana (face is at
+ * boundary), or the other side's refinement level is the same as that of
+ * this side, then handle the integration of these both cases together.
+ */
+ template <typename InputVector, class DH>
+ void
+ integrate_over_regular_face (const std::vector<const InputVector *> &solutions,
+ ParallelData<DH> ¶llel_data,
+ std::map<typename DH::face_iterator,std::vector<double> > &local_face_integrals,
+ const typename DH::active_cell_iterator &cell,
+ const unsigned int face_no,
+ dealii::hp::FEFaceValues<DH::dimension, DH::space_dimension> &fe_face_values_cell,
+ dealii::hp::FEFaceValues<DH::dimension, DH::space_dimension> &fe_face_values_neighbor)
+ {
+ const unsigned int dim = DH::dimension;
+
+ const typename DH::face_iterator face = cell->face(face_no);
+ const unsigned int n_solution_vectors = solutions.size();
+
+
+ // initialize data of the restriction
+ // of this cell to the present face
+ fe_face_values_cell.reinit (cell, face_no,
+ cell->active_fe_index());
+
+ // get gradients of the finite element
+ // function on this cell
+ for (unsigned int n=0; n<n_solution_vectors; ++n)
+ fe_face_values_cell.get_present_fe_values()
+ .get_function_gradients (*solutions[n], parallel_data.psi[n]);
+
+ // now compute over the other side of the face
+ if (face->at_boundary() == false)
+ // internal face; integrate jump of gradient across this face
+ {
+ Assert (cell->neighbor(face_no).state() == IteratorState::valid,
+ ExcInternalError());
+
+ const typename DH::active_cell_iterator neighbor = cell->neighbor(face_no);
+
+ // find which number the current face has relative to the
+ // neighboring cell
+ const unsigned int neighbor_neighbor
+ = cell->neighbor_of_neighbor (face_no);
+ Assert (neighbor_neighbor<GeometryInfo<dim>::faces_per_cell,
+ ExcInternalError());
+
+ // get restriction of finite element function of @p{neighbor} to the
+ // common face. in the hp case, use the quadrature formula that
+ // matches the one we would use for the present cell
+ fe_face_values_neighbor.reinit (neighbor, neighbor_neighbor,
+ cell->active_fe_index());
+
+ // get gradients on neighbor cell
+ for (unsigned int n=0; n<n_solution_vectors; ++n)
+ {
+ fe_face_values_neighbor.get_present_fe_values()
+ .get_function_gradients (*solutions[n],
+ parallel_data.neighbor_psi[n]);
+ }
+ }
+
+ // now go to the generic function that does all the other things
+ local_face_integrals[face] =
+ integrate_over_face (parallel_data, face, fe_face_values_cell);
}
*/
template <typename InputVector, class DH>
void
- integrate_over_irregular_face (const std::vector<const InputVector *> &solutions,
- ParallelData<DH> ¶llel_data,
+ integrate_over_irregular_face (const std::vector<const InputVector *> &solutions,
+ ParallelData<DH> ¶llel_data,
std::map<typename DH::face_iterator,std::vector<double> > &local_face_integrals,
const typename DH::active_cell_iterator &cell,
const unsigned int face_no,
const unsigned int dim = DH::dimension;
const typename DH::cell_iterator neighbor = cell->neighbor(face_no);
- const unsigned int n_q_points = parallel_data.face_quadratures[cell->active_fe_index()].size(),
- n_components = parallel_data.finite_element.n_components(),
- n_solution_vectors = solutions.size();
+ const unsigned int n_solution_vectors = solutions.size();
const typename DH::face_iterator
face=cell->face(face_no);
Assert (neighbor.state() == IteratorState::valid, ExcInternalError());
Assert (face->has_children(), ExcInternalError());
- // set up a vector of the gradients
- // of the finite element function
- // on this cell at the quadrature
- // points
+
+ // set up a vector of the gradients of the finite element function on
+ // this cell at the quadrature points
//
- // let psi be a short name for
- // [a grad u_h], where the second
- // index be the component of the
- // finite element, and the first
- // index the number of the
- // quadrature point
-
- // store which number @p{cell} has
- // in the list of neighbors of
+ // let psi be a short name for [a grad u_h], where the second index be
+ // the component of the finite element, and the first index the number
+ // of the quadrature point
+
+ // store which number @p{cell} has in the list of neighbors of
// @p{neighbor}
const unsigned int neighbor_neighbor
= cell->neighbor_of_neighbor (face_no);
// loop over all subfaces
for (unsigned int subface_no=0; subface_no<face->n_children(); ++subface_no)
{
- // get an iterator pointing to the
- // cell behind the present subface
+ // get an iterator pointing to the cell behind the present subface
const typename DH::active_cell_iterator neighbor_child
= cell->neighbor_child_on_subface (face_no, subface_no);
Assert (!neighbor_child->has_children(),
ExcInternalError());
- // restrict the finite element
- // on the present cell to the
- // subface
+ // restrict the finite element on the present cell to the subface
fe_subface_values.reinit (cell, face_no, subface_no,
cell->active_fe_index());
- // restrict the finite element
- // on the neighbor cell to the
- // common @p{subface}.
+ // restrict the finite element on the neighbor cell to the common
+ // @p{subface}.
fe_face_values.reinit (neighbor_child, neighbor_neighbor,
cell->active_fe_index());
- // store the gradient of the
- // solution in psi
+ // store the gradient of the solution in psi
for (unsigned int n=0; n<n_solution_vectors; ++n)
fe_subface_values.get_present_fe_values()
.get_function_gradients (*solutions[n], parallel_data.psi[n]);
- // store the gradient from the
- // neighbor's side in
- // @p{neighbor_psi}
+ // store the gradient from the neighbor's side in @p{neighbor_psi}
for (unsigned int n=0; n<n_solution_vectors; ++n)
fe_face_values.get_present_fe_values()
.get_function_gradients (*solutions[n], parallel_data.neighbor_psi[n]);
- // compute the jump in the gradients
- for (unsigned int n=0; n<n_solution_vectors; ++n)
- for (unsigned int component=0; component<n_components; ++component)
- for (unsigned int p=0; p<n_q_points; ++p)
- parallel_data.psi[n][p][component] -=
- parallel_data.neighbor_psi[n][p][component];
-
- // note that unlike for the
- // case of regular faces
- // (treated in the other
- // function of this class), we
- // have not to take care of
- // boundary faces here, since
- // they always are regular.
-
- // next we have to multiply this with
- // the normal vector. Since we have
- // taken the difference of gradients
- // for internal faces, we may chose
- // the normal vector of one cell,
- // taking that of the neighbor
- // would only change the sign. We take
- // the outward normal.
- //
- // let phi be the name of the integrand
-
- parallel_data.normal_vectors
- = fe_face_values.get_present_fe_values().get_normal_vectors();
-
-
- for (unsigned int n=0; n<n_solution_vectors; ++n)
- for (unsigned int component=0; component<n_components; ++component)
- for (unsigned int point=0; point<n_q_points; ++point)
- parallel_data.phi[n][point][component] = (parallel_data.psi[n][point][component]*
- parallel_data.normal_vectors[point]);
-
- // if a coefficient was given: use that
- // to scale the jump in the gradient
- if (parallel_data.coefficients != 0)
- {
- // scalar coefficient
- if (parallel_data.coefficients->n_components == 1)
- {
- parallel_data.coefficients
- ->value_list (fe_face_values.get_present_fe_values()
- .get_quadrature_points(),
- parallel_data.coefficient_values1);
- for (unsigned int n=0; n<n_solution_vectors; ++n)
- for (unsigned int component=0; component<n_components; ++component)
- for (unsigned int point=0; point<n_q_points; ++point)
- parallel_data.phi[n][point][component] *=
- parallel_data.coefficient_values1[point];
- }
- else
- // vector-valued coefficient
- {
- parallel_data.coefficients
- ->vector_value_list (fe_face_values.get_present_fe_values()
- .get_quadrature_points(),
- parallel_data.coefficient_values);
- for (unsigned int n=0; n<n_solution_vectors; ++n)
- for (unsigned int component=0; component<n_components; ++component)
- for (unsigned int point=0; point<n_q_points; ++point)
- parallel_data.phi[n][point][component] *=
- parallel_data.coefficient_values[point](component);
- }
- }
-
- // get the weights for the
- // integration. note that it
- // does not matter whether we
- // take the JxW values from the
- // fe_face_values or the
- // fe_subface_values, as the
- // first is on the small
- // neighbor cell, while the
- // latter is on the refined
- // face of the big cell here
- parallel_data.JxW_values
- = fe_face_values.get_present_fe_values().get_JxW_values();
-
- // take the square of the phi[i]
- // for integration, and sum up
- std::vector<double> face_integral (n_solution_vectors, 0);
- for (unsigned int n=0; n<n_solution_vectors; ++n)
- for (unsigned int component=0; component<n_components; ++component)
- if (parallel_data.component_mask[component] == true)
- for (unsigned int p=0; p<n_q_points; ++p)
- face_integral[n] += dealii::sqr(parallel_data.phi[n][p][component]) *
- parallel_data.JxW_values[p];
-
- local_face_integrals[neighbor_child->face(neighbor_neighbor)]
- = face_integral;
+ // call generic evaluate function
+ local_face_integrals[neighbor_child->face(neighbor_neighbor)] =
+ integrate_over_face (parallel_data, face, fe_face_values);
}
-
- // finally loop over all subfaces to
- // collect the contributions of the
- // subfaces and store them with the
- // mother face
+ // finally loop over all subfaces to collect the contributions of the
+ // subfaces and store them with the mother face
std::vector<double> sum (n_solution_vectors, 0);
for (unsigned int subface_no=0; subface_no<face->n_children(); ++subface_no)
{
/**
- * Computate the error on the faces of a
- * single cell.
+ * Computate the error on the faces of a single cell.
*
- * This function is only needed
- * in two or three dimensions.
- * The error estimator in one
- * dimension is implemented
- * seperatly.
+ * This function is only needed in two or three dimensions. The error
+ * estimator in one dimension is implemented separately.
*/
- template <int dim, int spacedim, typename InputVector, class DH>
+ template <typename InputVector, class DH>
void
estimate_one_cell (const typename DH::active_cell_iterator &cell,
ParallelData<DH> ¶llel_data,
std::map<typename DH::face_iterator,std::vector<double> > &local_face_integrals,
const std::vector<const InputVector *> &solutions)
{
+ const unsigned int dim = DH::dimension;
const unsigned int n_solution_vectors = solutions.size();
const types::subdomain_id subdomain_id = parallel_data.subdomain_id;
const unsigned int material_id = parallel_data.material_id;
- // empty our own copy of the local face
- // integrals
+ // empty our own copy of the local face integrals
local_face_integrals.clear();
// loop over all faces of this cell
const typename DH::face_iterator
face=cell->face(face_no);
- // make sure we do work
- // only once: this face
- // may either be regular
- // or irregular. if it is
- // regular and has a
- // neighbor, then we
- // visit the face twice,
- // once from every
- // side. let the one with
- // the lower index do the
- // work. if it is at the
- // boundary, or if the
- // face is irregular,
- // then do the work below
+ // make sure we do work only once: this face may either be regular
+ // or irregular. if it is regular and has a neighbor, then we visit
+ // the face twice, once from every side. let the one with the lower
+ // index do the work. if it is at the boundary, or if the face is
+ // irregular, then do the work below
if ((face->has_children() == false) &&
!cell->at_boundary(face_no) &&
(!cell->neighbor_is_coarser(face_no) &&
cell->neighbor(face_no)->level() < cell->level()))))
continue;
- // if the neighboring cell is less
- // refined than the present one,
- // then do nothing since we
- // integrate over the subfaces when
- // we visit the coarse cells.
+ // if the neighboring cell is less refined than the present one,
+ // then do nothing since we integrate over the subfaces when we
+ // visit the coarse cells.
if (face->at_boundary() == false)
if (cell->neighbor_is_coarser(face_no))
continue;
- // if this face is part of the
- // boundary but not of the neumann
- // boundary -> nothing to
- // do. However, to make things
- // easier when summing up the
- // contributions of the faces of
- // cells, we enter this face into
- // the list of faces with
- // contribution zero.
+ // if this face is part of the boundary but not of the neumann
+ // boundary -> nothing to do. However, to make things easier when
+ // summing up the contributions of the faces of cells, we enter this
+ // face into the list of faces with contribution zero.
if (face->at_boundary()
&&
(parallel_data.neumann_bc->find(face->boundary_indicator()) ==
continue;
}
- // finally: note that we only have
- // to do something if either the
- // present cell is on the subdomain
- // we care for (and the same for
- // material_id), or if one of the
- // neighbors behind the face is on
+ // finally: note that we only have to do something if either the
+ // present cell is on the subdomain we care for (and the same for
+ // material_id), or if one of the neighbors behind the face is on
// the subdomain we care for
if ( ! ( ((subdomain_id == numbers::invalid_subdomain_id)
||
||
(cell->material_id() == material_id))) )
{
- // ok, cell is unwanted, but
- // maybe its neighbor behind
- // the face we presently work
- // on? oh is there a face at
- // all?
+ // ok, cell is unwanted, but maybe its neighbor behind the face
+ // we presently work on? oh is there a face at all?
if (face->at_boundary())
continue;
}
}
- // so if none of the neighbors
- // cares for this subdomain or
- // material either, then try
- // next face
+ // so if none of the neighbors cares for this subdomain or
+ // material either, then try next face
if (care_for_cell == false)
continue;
}
- // so now we know that we care for
- // this face, let's do something
- // about it. first re-size the
- // arrays we may use to the correct
+ // so now we know that we care for this face, let's do something
+ // about it. first re-size the arrays we may use to the correct
// size:
parallel_data.resize (cell->active_fe_index());
// then do the actual integration
if (face->has_children() == false)
- // if the face is a regular one,
- // i.e. either on the other side
- // there is nirvana (face is at
- // boundary), or the other side's
- // refinement level is the same
- // as that of this side, then
- // handle the integration of
- // these both cases together
+ // if the face is a regular one, i.e. either on the other side
+ // there is nirvana (face is at boundary), or the other side's
+ // refinement level is the same as that of this side, then handle
+ // the integration of these both cases together
integrate_over_regular_face (solutions,
parallel_data,
local_face_integrals,
parallel_data.fe_face_values_neighbor);
else
- // otherwise we need to do some
- // special computations which do
- // not fit into the framework of
- // the above function
+ // otherwise we need to do some special computations which do not
+ // fit into the framework of the above function
integrate_over_irregular_face (solutions,
parallel_data,
local_face_integrals,
-
-
-template <int spacedim>
-template <typename InputVector, class DH>
-void
-KellyErrorEstimator<1,spacedim>::
-estimate (const Mapping<1,spacedim> &mapping,
- const DH &dof_handler,
- const Quadrature<0> &quadrature,
- const typename FunctionMap<spacedim>::type &neumann_bc,
- const InputVector &solution,
- Vector<float> &error,
- const ComponentMask &component_mask,
- const Function<spacedim> *coefficients,
- const unsigned int n_threads,
- const types::subdomain_id subdomain_id,
- const types::material_id material_id)
-{
- // just pass on to the other function
- const std::vector<const InputVector *> solutions (1, &solution);
- std::vector<Vector<float>*> errors (1, &error);
- estimate (mapping, dof_handler, quadrature, neumann_bc, solutions, errors,
- component_mask, coefficients, n_threads, subdomain_id, material_id);
-}
-
-
-
-template <int spacedim>
-template <typename InputVector, class DH>
-void
-KellyErrorEstimator<1,spacedim>::
-estimate (const DH &dof_handler,
- const Quadrature<0> &quadrature,
- const typename FunctionMap<spacedim>::type &neumann_bc,
- const InputVector &solution,
- Vector<float> &error,
- const ComponentMask &component_mask,
- const Function<spacedim> *coefficients,
- const unsigned int n_threads,
- const types::subdomain_id subdomain_id,
- const types::material_id material_id)
-{
- estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solution,
- error, component_mask, coefficients, n_threads, subdomain_id, material_id);
-}
-
-
-
-template <int spacedim>
-template <typename InputVector, class DH>
-void
-KellyErrorEstimator<1,spacedim>::
-estimate (const DH &dof_handler,
- const Quadrature<0> &quadrature,
- const typename FunctionMap<spacedim>::type &neumann_bc,
- const std::vector<const InputVector *> &solutions,
- std::vector<Vector<float>*> &errors,
- const ComponentMask &component_mask,
- const Function<spacedim> *coefficients,
- const unsigned int n_threads,
- const types::subdomain_id subdomain_id,
- const types::material_id material_id)
-{
- estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solutions,
- errors, component_mask, coefficients, n_threads, subdomain_id, material_id);
-}
-
-
-
-template <int spacedim>
-template <typename InputVector, class DH>
-void
-KellyErrorEstimator<1,spacedim>::
-estimate (const Mapping<1,spacedim> &mapping,
- const DH &dof_handler,
- const hp::QCollection<0> &quadrature,
- const typename FunctionMap<spacedim>::type &neumann_bc,
- const InputVector &solution,
- Vector<float> &error,
- const ComponentMask &component_mask,
- const Function<spacedim> *coefficients,
- const unsigned int n_threads,
- const types::subdomain_id subdomain_id,
- const types::material_id material_id)
-{
- // just pass on to the other function
- const std::vector<const InputVector *> solutions (1, &solution);
- std::vector<Vector<float>*> errors (1, &error);
- estimate (mapping, dof_handler, quadrature, neumann_bc, solutions, errors,
- component_mask, coefficients, n_threads, subdomain_id, material_id);
-}
-
-
-template <int spacedim>
-template <typename InputVector, class DH>
-void
-KellyErrorEstimator<1,spacedim>::
-estimate (const DH &dof_handler,
- const hp::QCollection<0> &quadrature,
- const typename FunctionMap<spacedim>::type &neumann_bc,
- const InputVector &solution,
- Vector<float> &error,
- const ComponentMask &component_mask,
- const Function<spacedim> *coefficients,
- const unsigned int n_threads,
- const types::subdomain_id subdomain_id,
- const types::material_id material_id)
-{
- estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solution,
- error, component_mask, coefficients, n_threads, subdomain_id, material_id);
-}
-
-
-
-template <int spacedim>
-template <typename InputVector, class DH>
-void
-KellyErrorEstimator<1,spacedim>::
-estimate (const DH &dof_handler,
- const hp::QCollection<0> &quadrature,
- const typename FunctionMap<spacedim>::type &neumann_bc,
- const std::vector<const InputVector *> &solutions,
- std::vector<Vector<float>*> &errors,
- const ComponentMask &component_mask,
- const Function<spacedim> *coefficients,
- const unsigned int n_threads,
- const types::subdomain_id subdomain_id,
- const types::material_id material_id)
-{
- estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solutions,
- errors, component_mask, coefficients, n_threads, subdomain_id, material_id);
-}
-
-
-
-
-template <int spacedim>
-template <typename InputVector, class DH>
-void KellyErrorEstimator<1,spacedim>::
-estimate (const Mapping<1,spacedim> &/*mapping*/,
- const DH &/*dof_handler*/,
- const hp::QCollection<0> &,
- const typename FunctionMap<spacedim>::type &/*neumann_bc*/,
- const std::vector<const InputVector *> &/*solutions*/,
- std::vector<Vector<float>*> &/*errors*/,
- const ComponentMask &/*component_mask_*/,
- const Function<spacedim> */*coefficient*/,
- const unsigned int,
- const types::subdomain_id /*subdomain_id*/,
- const types::material_id /*material_id*/)
-{
- Assert (false, ExcInternalError());
-}
-
-
-
-template <int spacedim>
-template <typename InputVector, class DH>
-void KellyErrorEstimator<1,spacedim>::
-estimate (const Mapping<1,spacedim> &mapping,
- const DH &dof_handler,
- const Quadrature<0> &,
- const typename FunctionMap<spacedim>::type &neumann_bc,
- const std::vector<const InputVector *> &solutions,
- std::vector<Vector<float>*> &errors,
- const ComponentMask &component_mask,
- const Function<spacedim> *coefficient,
- const unsigned int,
- const types::subdomain_id subdomain_id_,
- const types::material_id material_id)
-{
-#ifdef DEAL_II_WITH_P4EST
- if (dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>*>
- (&dof_handler.get_tria())
- != 0)
- Assert ((subdomain_id_ == numbers::invalid_subdomain_id)
- ||
- (subdomain_id_ ==
- dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>&>
- (dof_handler.get_tria()).locally_owned_subdomain()),
- ExcMessage ("For parallel distributed triangulations, the only "
- "valid subdomain_id that can be passed here is the "
- "one that corresponds to the locally owned subdomain id."));
-
- const types::subdomain_id subdomain_id
- = ((dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>*>
- (&dof_handler.get_tria())
- != 0)
- ?
- dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>&>
- (dof_handler.get_tria()).locally_owned_subdomain()
- :
- subdomain_id_);
-#else
- const types::subdomain_id subdomain_id
- = subdomain_id_;
-#endif
-
- const unsigned int n_components = dof_handler.get_fe().n_components();
- const unsigned int n_solution_vectors = solutions.size();
-
- // sanity checks
- Assert (neumann_bc.find(numbers::internal_face_boundary_id) == neumann_bc.end(),
- ExcInvalidBoundaryIndicator());
-
- for (typename FunctionMap<spacedim>::type::const_iterator i=neumann_bc.begin();
- i!=neumann_bc.end(); ++i)
- Assert (i->second->n_components == n_components, ExcInvalidBoundaryFunction());
-
- Assert (component_mask.represents_n_components(n_components),
- ExcInvalidComponentMask());
- Assert (component_mask.n_selected_components(n_components) > 0,
- ExcInvalidComponentMask());
-
- Assert ((coefficient == 0) ||
- (coefficient->n_components == n_components) ||
- (coefficient->n_components == 1),
- ExcInvalidCoefficient());
-
- Assert (solutions.size() > 0,
- ExcNoSolutions());
- Assert (solutions.size() == errors.size(),
- ExcIncompatibleNumberOfElements(solutions.size(), errors.size()));
- for (unsigned int n=0; n<solutions.size(); ++n)
- Assert (solutions[n]->size() == dof_handler.n_dofs(),
- ExcInvalidSolutionVector());
-
- Assert ((coefficient == 0) ||
- (coefficient->n_components == n_components) ||
- (coefficient->n_components == 1),
- ExcInvalidCoefficient());
-
- for (typename FunctionMap<spacedim>::type::const_iterator i=neumann_bc.begin();
- i!=neumann_bc.end(); ++i)
- Assert (i->second->n_components == n_components,
- ExcInvalidBoundaryFunction());
-
- // reserve one slot for each cell and set
- // it to zero
- for (unsigned int n=0; n<n_solution_vectors; ++n)
- (*errors[n]).reinit (dof_handler.get_tria().n_active_cells());
-
- // fields to get the gradients on
- // the present and the neighbor cell.
- //
- // for the neighbor gradient, we
- // need several auxiliary fields,
- // depending on the way we get it
- // (see below)
- std::vector<std::vector<std::vector<Tensor<1,spacedim> > > >
- gradients_here (n_solution_vectors,
- std::vector<std::vector<Tensor<1,spacedim> > >(2, std::vector<Tensor<1,spacedim> >(n_components)));
- std::vector<std::vector<std::vector<Tensor<1,spacedim> > > >
- gradients_neighbor (gradients_here);
- std::vector<Vector<double> >
- grad_neighbor (n_solution_vectors, Vector<double>(n_components));
-
- // reserve some space for
- // coefficient values at one point.
- // if there is no coefficient, then
- // we fill it by unity once and for
- // all and don't set it any more
- Vector<double> coefficient_values (n_components);
- if (coefficient == 0)
- for (unsigned int c=0; c<n_components; ++c)
- coefficient_values(c) = 1;
-
- const QTrapez<1> quadrature;
- const hp::QCollection<1> q_collection(quadrature);
-
- const hp::FECollection<1,spacedim> fe (dof_handler.get_fe());
-
- hp::MappingCollection<1,spacedim> mapping_collection;
- mapping_collection.push_back (mapping);
-
- hp::FEValues<1,spacedim> fe_values (mapping_collection, fe, q_collection,
- update_gradients);
-
- // loop over all cells and do something on
- // the cells which we're told to work
- // on. note that the error indicator is
- // only a sum over the two contributions
- // from the two vertices of each cell.
- typename DH::active_cell_iterator cell = dof_handler.begin_active();
- for (unsigned int cell_index=0; cell != dof_handler.end();
- ++cell, ++cell_index)
- if (((subdomain_id == numbers::invalid_subdomain_id)
- ||
- (cell->subdomain_id() == subdomain_id))
- &&
- ((material_id == numbers::invalid_material_id)
- ||
- (cell->material_id() == material_id)))
- {
- for (unsigned int n=0; n<n_solution_vectors; ++n)
- (*errors[n])(cell_index) = 0;
-
- // loop over the two points bounding
- // this line. n==0 is left point,
- // n==1 is right point
- for (unsigned int n=0; n<2; ++n)
- {
- // find left or right active
- // neighbor
- typename DH::cell_iterator neighbor = cell->neighbor(n);
- if (neighbor.state() == IteratorState::valid)
- while (neighbor->has_children())
- neighbor = neighbor->child(n==0 ? 1 : 0);
-
- // now get the gradients on the
- // both sides of the point
- fe_values.reinit (cell);
-
- for (unsigned int s=0; s<n_solution_vectors; ++s)
- fe_values.get_present_fe_values()
- .get_function_gradients (*solutions[s], gradients_here[s]);
-
- if (neighbor.state() == IteratorState::valid)
- {
- fe_values.reinit (neighbor);
-
- for (unsigned int s=0; s<n_solution_vectors; ++s)
- fe_values.get_present_fe_values()
- .get_function_gradients (*solutions[s],
- gradients_neighbor[s]);
-
- // extract the
- // gradients of all the
- // components. [0]
- // means: x-derivative,
- // which is the only
- // one here
- for (unsigned int s=0; s<n_solution_vectors; ++s)
- for (unsigned int c=0; c<n_components; ++c)
- grad_neighbor[s](c)
- = gradients_neighbor[s][n==0 ? 1 : 0][c][0];
- }
- else if (neumann_bc.find(n) != neumann_bc.end())
- // if Neumann b.c., then fill
- // the gradients field which
- // will be used later on.
- {
- if (n_components==1)
- {
- const double
- v = neumann_bc.find(n)->second->value(cell->vertex(0));
-
- for (unsigned int s=0; s<n_solution_vectors; ++s)
- grad_neighbor[s](0) = v;
- }
- else
- {
- Vector<double> v(n_components);
- neumann_bc.find(n)->second->vector_value(cell->vertex(0), v);
-
- for (unsigned int s=0; s<n_solution_vectors; ++s)
- grad_neighbor[s] = v;
- }
- }
- else
- // fill with zeroes.
- for (unsigned int s=0; s<n_solution_vectors; ++s)
- grad_neighbor[s] = 0;
-
- // if there is a
- // coefficient, then
- // evaluate it at the
- // present position. if
- // there is none, reuse the
- // preset values.
- if (coefficient != 0)
- {
- if (coefficient->n_components == 1)
- {
- const double c_value = coefficient->value (cell->vertex(n));
- for (unsigned int c=0; c<n_components; ++c)
- coefficient_values(c) = c_value;
- }
- else
- coefficient->vector_value(cell->vertex(n),
- coefficient_values);
- }
-
-
- for (unsigned int s=0; s<n_solution_vectors; ++s)
- for (unsigned int component=0; component<n_components; ++component)
- if (component_mask[component] == true)
- {
- // get gradient
- // here. [0] means
- // x-derivative
- // (there is no
- // other component
- // in 1d)
- const double grad_here = gradients_here[s][n][component][0];
-
- const double jump = ((grad_here - grad_neighbor[s](component)) *
- coefficient_values(component));
- (*errors[s])(cell_index) += jump*jump * cell->diameter();
- }
- }
-
- for (unsigned int s=0; s<n_solution_vectors; ++s)
- (*errors[s])(cell_index) = std::sqrt((*errors[s])(cell_index));
- }
-}
-
-
-
-
-
-
// the following function is still independent of dimension, but it
// calls dimension dependent functions
template <int dim, int spacedim>
const unsigned int n_solution_vectors = solutions.size();
- // Map of integrals indexed by
- // the corresponding face. In this map
- // we store the integrated jump of the
- // gradient for each face.
- // At the end of the function, we again
- // loop over the cells and collect the
- // contributions of the different faces
- // of the cell.
+ // Map of integrals indexed by the corresponding face. In this map we store
+ // the integrated jump of the gradient for each face. At the end of the
+ // function, we again loop over the cells and collect the contributions of
+ // the different faces of the cell.
std::map<typename DH::face_iterator,std::vector<double> > face_integrals;
- // all the data needed in the error
- // estimator by each of the threads
- // is gathered in the following
- // stuctures
+ // all the data needed in the error estimator by each of the threads is
+ // gathered in the following structures
const hp::MappingCollection<dim,spacedim> mapping_collection(mapping);
const internal::ParallelData<DH>
parallel_data (dof_handler.get_fe(),
// now let's work on all those cells:
WorkStream::run (dof_handler.begin_active(),
static_cast<typename DH::active_cell_iterator>(dof_handler.end()),
- std_cxx1x::bind (&internal::estimate_one_cell<dim,spacedim,InputVector,DH>,
+ std_cxx1x::bind (&internal::estimate_one_cell<InputVector,DH>,
std_cxx1x::_1, std_cxx1x::_2, std_cxx1x::_3, std_cxx1x::ref(solutions)),
std_cxx1x::bind (&internal::copy_local_to_global<DH>,
std_cxx1x::_1, std_cxx1x::ref(face_integrals)),
parallel_data,
sample_local_face_integrals);
- // finally add up the contributions of the
- // faces for each cell
+ // finally add up the contributions of the faces for each cell
- // reserve one slot for each cell and set
- // it to zero
+ // reserve one slot for each cell and set it to zero
for (unsigned int n=0; n<n_solution_vectors; ++n)
{
(*errors[n]).reinit (dof_handler.get_tria().n_active_cells());
(*errors[n])(i)=0;
}
- // now walk over all cells and collect
- // information from the faces. only do
- // something if this is a cell we care for
- // based on the subdomain id
+ // now walk over all cells and collect information from the faces. only do
+ // something if this is a cell we care for based on the subdomain id
unsigned int present_cell=0;
for (typename DH::active_cell_iterator cell=dof_handler.begin_active();
cell!=dof_handler.end();
for (unsigned int n=0; n<n_solution_vectors; ++n)
{
- // make sure that we have
- // written a meaningful value
- // into this slot
+ // make sure that we have written a meaningful value into this
+ // slot
Assert (face_integrals[cell->face(face_no)][n] >= 0,
ExcInternalError());
for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; DH : DOFHANDLER_TEMPLATES )
{
-#if deal_II_dimension <= deal_II_space_dimension
+#if deal_II_dimension != 1 && deal_II_dimension <= deal_II_space_dimension
template
void
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/thread_management.h>
+#include <deal.II/base/quadrature.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/work_stream.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/base/geometry_info.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/fe/fe.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/hp/fe_values.h>
+#include <deal.II/fe/fe_update_flags.h>
+#include <deal.II/fe/mapping_q1.h>
+#include <deal.II/hp/q_collection.h>
+#include <deal.II/hp/mapping_collection.h>
+#include <deal.II/numerics/error_estimator.h>
+
+#include <deal.II/base/std_cxx1x/bind.h>
+
+#include <numeric>
+#include <algorithm>
+#include <cmath>
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+template <int spacedim>
+template <typename InputVector, class DH>
+void
+KellyErrorEstimator<1,spacedim>::
+estimate (const Mapping<1,spacedim> &mapping,
+ const DH &dof_handler,
+ const Quadrature<0> &quadrature,
+ const typename FunctionMap<spacedim>::type &neumann_bc,
+ const InputVector &solution,
+ Vector<float> &error,
+ const ComponentMask &component_mask,
+ const Function<spacedim> *coefficients,
+ const unsigned int n_threads,
+ const types::subdomain_id subdomain_id,
+ const types::material_id material_id)
+{
+ // just pass on to the other function
+ const std::vector<const InputVector *> solutions (1, &solution);
+ std::vector<Vector<float>*> errors (1, &error);
+ estimate (mapping, dof_handler, quadrature, neumann_bc, solutions, errors,
+ component_mask, coefficients, n_threads, subdomain_id, material_id);
+}
+
+
+
+template <int spacedim>
+template <typename InputVector, class DH>
+void
+KellyErrorEstimator<1,spacedim>::
+estimate (const DH &dof_handler,
+ const Quadrature<0> &quadrature,
+ const typename FunctionMap<spacedim>::type &neumann_bc,
+ const InputVector &solution,
+ Vector<float> &error,
+ const ComponentMask &component_mask,
+ const Function<spacedim> *coefficients,
+ const unsigned int n_threads,
+ const types::subdomain_id subdomain_id,
+ const types::material_id material_id)
+{
+ estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solution,
+ error, component_mask, coefficients, n_threads, subdomain_id, material_id);
+}
+
+
+
+template <int spacedim>
+template <typename InputVector, class DH>
+void
+KellyErrorEstimator<1,spacedim>::
+estimate (const DH &dof_handler,
+ const Quadrature<0> &quadrature,
+ const typename FunctionMap<spacedim>::type &neumann_bc,
+ const std::vector<const InputVector *> &solutions,
+ std::vector<Vector<float>*> &errors,
+ const ComponentMask &component_mask,
+ const Function<spacedim> *coefficients,
+ const unsigned int n_threads,
+ const types::subdomain_id subdomain_id,
+ const types::material_id material_id)
+{
+ estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solutions,
+ errors, component_mask, coefficients, n_threads, subdomain_id, material_id);
+}
+
+
+
+template <int spacedim>
+template <typename InputVector, class DH>
+void
+KellyErrorEstimator<1,spacedim>::
+estimate (const Mapping<1,spacedim> &mapping,
+ const DH &dof_handler,
+ const hp::QCollection<0> &quadrature,
+ const typename FunctionMap<spacedim>::type &neumann_bc,
+ const InputVector &solution,
+ Vector<float> &error,
+ const ComponentMask &component_mask,
+ const Function<spacedim> *coefficients,
+ const unsigned int n_threads,
+ const types::subdomain_id subdomain_id,
+ const types::material_id material_id)
+{
+ // just pass on to the other function
+ const std::vector<const InputVector *> solutions (1, &solution);
+ std::vector<Vector<float>*> errors (1, &error);
+ estimate (mapping, dof_handler, quadrature, neumann_bc, solutions, errors,
+ component_mask, coefficients, n_threads, subdomain_id, material_id);
+}
+
+
+template <int spacedim>
+template <typename InputVector, class DH>
+void
+KellyErrorEstimator<1,spacedim>::
+estimate (const DH &dof_handler,
+ const hp::QCollection<0> &quadrature,
+ const typename FunctionMap<spacedim>::type &neumann_bc,
+ const InputVector &solution,
+ Vector<float> &error,
+ const ComponentMask &component_mask,
+ const Function<spacedim> *coefficients,
+ const unsigned int n_threads,
+ const types::subdomain_id subdomain_id,
+ const types::material_id material_id)
+{
+ estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solution,
+ error, component_mask, coefficients, n_threads, subdomain_id, material_id);
+}
+
+
+
+template <int spacedim>
+template <typename InputVector, class DH>
+void
+KellyErrorEstimator<1,spacedim>::
+estimate (const DH &dof_handler,
+ const hp::QCollection<0> &quadrature,
+ const typename FunctionMap<spacedim>::type &neumann_bc,
+ const std::vector<const InputVector *> &solutions,
+ std::vector<Vector<float>*> &errors,
+ const ComponentMask &component_mask,
+ const Function<spacedim> *coefficients,
+ const unsigned int n_threads,
+ const types::subdomain_id subdomain_id,
+ const types::material_id material_id)
+{
+ estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solutions,
+ errors, component_mask, coefficients, n_threads, subdomain_id, material_id);
+}
+
+
+
+
+template <int spacedim>
+template <typename InputVector, class DH>
+void KellyErrorEstimator<1,spacedim>::
+estimate (const Mapping<1,spacedim> &/*mapping*/,
+ const DH &/*dof_handler*/,
+ const hp::QCollection<0> &,
+ const typename FunctionMap<spacedim>::type &/*neumann_bc*/,
+ const std::vector<const InputVector *> &/*solutions*/,
+ std::vector<Vector<float>*> &/*errors*/,
+ const ComponentMask &/*component_mask_*/,
+ const Function<spacedim> */*coefficient*/,
+ const unsigned int,
+ const types::subdomain_id /*subdomain_id*/,
+ const types::material_id /*material_id*/)
+{
+ Assert (false, ExcInternalError());
+}
+
+
+
+template <int spacedim>
+template <typename InputVector, class DH>
+void KellyErrorEstimator<1,spacedim>::
+estimate (const Mapping<1,spacedim> &mapping,
+ const DH &dof_handler,
+ const Quadrature<0> &,
+ const typename FunctionMap<spacedim>::type &neumann_bc,
+ const std::vector<const InputVector *> &solutions,
+ std::vector<Vector<float>*> &errors,
+ const ComponentMask &component_mask,
+ const Function<spacedim> *coefficient,
+ const unsigned int,
+ const types::subdomain_id subdomain_id_,
+ const types::material_id material_id)
+{
+#ifdef DEAL_II_WITH_P4EST
+ if (dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>*>
+ (&dof_handler.get_tria())
+ != 0)
+ Assert ((subdomain_id_ == numbers::invalid_subdomain_id)
+ ||
+ (subdomain_id_ ==
+ dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>&>
+ (dof_handler.get_tria()).locally_owned_subdomain()),
+ ExcMessage ("For parallel distributed triangulations, the only "
+ "valid subdomain_id that can be passed here is the "
+ "one that corresponds to the locally owned subdomain id."));
+
+ const types::subdomain_id subdomain_id
+ = ((dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>*>
+ (&dof_handler.get_tria())
+ != 0)
+ ?
+ dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>&>
+ (dof_handler.get_tria()).locally_owned_subdomain()
+ :
+ subdomain_id_);
+#else
+ const types::subdomain_id subdomain_id
+ = subdomain_id_;
+#endif
+
+ const unsigned int n_components = dof_handler.get_fe().n_components();
+ const unsigned int n_solution_vectors = solutions.size();
+
+ // sanity checks
+ Assert (neumann_bc.find(numbers::internal_face_boundary_id) == neumann_bc.end(),
+ ExcInvalidBoundaryIndicator());
+
+ for (typename FunctionMap<spacedim>::type::const_iterator i=neumann_bc.begin();
+ i!=neumann_bc.end(); ++i)
+ Assert (i->second->n_components == n_components, ExcInvalidBoundaryFunction());
+
+ Assert (component_mask.represents_n_components(n_components),
+ ExcInvalidComponentMask());
+ Assert (component_mask.n_selected_components(n_components) > 0,
+ ExcInvalidComponentMask());
+
+ Assert ((coefficient == 0) ||
+ (coefficient->n_components == n_components) ||
+ (coefficient->n_components == 1),
+ ExcInvalidCoefficient());
+
+ Assert (solutions.size() > 0,
+ ExcNoSolutions());
+ Assert (solutions.size() == errors.size(),
+ ExcIncompatibleNumberOfElements(solutions.size(), errors.size()));
+ for (unsigned int n=0; n<solutions.size(); ++n)
+ Assert (solutions[n]->size() == dof_handler.n_dofs(),
+ ExcInvalidSolutionVector());
+
+ Assert ((coefficient == 0) ||
+ (coefficient->n_components == n_components) ||
+ (coefficient->n_components == 1),
+ ExcInvalidCoefficient());
+
+ for (typename FunctionMap<spacedim>::type::const_iterator i=neumann_bc.begin();
+ i!=neumann_bc.end(); ++i)
+ Assert (i->second->n_components == n_components,
+ ExcInvalidBoundaryFunction());
+
+ // reserve one slot for each cell and set it to zero
+ for (unsigned int n=0; n<n_solution_vectors; ++n)
+ (*errors[n]).reinit (dof_handler.get_tria().n_active_cells());
+
+ // fields to get the gradients on the present and the neighbor cell.
+ //
+ // for the neighbor gradient, we need several auxiliary fields, depending on
+ // the way we get it (see below)
+ std::vector<std::vector<std::vector<Tensor<1,spacedim> > > >
+ gradients_here (n_solution_vectors,
+ std::vector<std::vector<Tensor<1,spacedim> > >(2, std::vector<Tensor<1,spacedim> >(n_components)));
+ std::vector<std::vector<std::vector<Tensor<1,spacedim> > > >
+ gradients_neighbor (gradients_here);
+ std::vector<Vector<double> >
+ grad_neighbor (n_solution_vectors, Vector<double>(n_components));
+
+ // reserve some space for coefficient values at one point. if there is no
+ // coefficient, then we fill it by unity once and for all and don't set it
+ // any more
+ Vector<double> coefficient_values (n_components);
+ if (coefficient == 0)
+ for (unsigned int c=0; c<n_components; ++c)
+ coefficient_values(c) = 1;
+
+ const QTrapez<1> quadrature;
+ const hp::QCollection<1> q_collection(quadrature);
+
+ const hp::FECollection<1,spacedim> fe (dof_handler.get_fe());
+
+ hp::MappingCollection<1,spacedim> mapping_collection;
+ mapping_collection.push_back (mapping);
+
+ hp::FEValues<1,spacedim> fe_values (mapping_collection, fe, q_collection,
+ update_gradients);
+
+ // loop over all cells and do something on the cells which we're told to
+ // work on. note that the error indicator is only a sum over the two
+ // contributions from the two vertices of each cell.
+ typename DH::active_cell_iterator cell = dof_handler.begin_active();
+ for (unsigned int cell_index=0; cell != dof_handler.end();
+ ++cell, ++cell_index)
+ if (((subdomain_id == numbers::invalid_subdomain_id)
+ ||
+ (cell->subdomain_id() == subdomain_id))
+ &&
+ ((material_id == numbers::invalid_material_id)
+ ||
+ (cell->material_id() == material_id)))
+ {
+ for (unsigned int n=0; n<n_solution_vectors; ++n)
+ (*errors[n])(cell_index) = 0;
+
+ // loop over the two points bounding this line. n==0 is left point,
+ // n==1 is right point
+ for (unsigned int n=0; n<2; ++n)
+ {
+ // find left or right active neighbor
+ typename DH::cell_iterator neighbor = cell->neighbor(n);
+ if (neighbor.state() == IteratorState::valid)
+ while (neighbor->has_children())
+ neighbor = neighbor->child(n==0 ? 1 : 0);
+
+ // now get the gradients on the both sides of the point
+ fe_values.reinit (cell);
+
+ for (unsigned int s=0; s<n_solution_vectors; ++s)
+ fe_values.get_present_fe_values()
+ .get_function_gradients (*solutions[s], gradients_here[s]);
+
+ if (neighbor.state() == IteratorState::valid)
+ {
+ fe_values.reinit (neighbor);
+
+ for (unsigned int s=0; s<n_solution_vectors; ++s)
+ fe_values.get_present_fe_values()
+ .get_function_gradients (*solutions[s],
+ gradients_neighbor[s]);
+
+ // extract the gradients of all the components. [0] means:
+ // x-derivative, which is the only one here
+ for (unsigned int s=0; s<n_solution_vectors; ++s)
+ for (unsigned int c=0; c<n_components; ++c)
+ grad_neighbor[s](c)
+ = gradients_neighbor[s][n==0 ? 1 : 0][c][0];
+ }
+ else if (neumann_bc.find(n) != neumann_bc.end())
+ // if Neumann b.c., then fill the gradients field which will be
+ // used later on.
+ {
+ if (n_components==1)
+ {
+ const double
+ v = neumann_bc.find(n)->second->value(cell->vertex(0));
+
+ for (unsigned int s=0; s<n_solution_vectors; ++s)
+ grad_neighbor[s](0) = v;
+ }
+ else
+ {
+ Vector<double> v(n_components);
+ neumann_bc.find(n)->second->vector_value(cell->vertex(0), v);
+
+ for (unsigned int s=0; s<n_solution_vectors; ++s)
+ grad_neighbor[s] = v;
+ }
+ }
+ else
+ // fill with zeroes.
+ for (unsigned int s=0; s<n_solution_vectors; ++s)
+ grad_neighbor[s] = 0;
+
+ // if there is a coefficient, then evaluate it at the present
+ // position. if there is none, reuse the preset values.
+ if (coefficient != 0)
+ {
+ if (coefficient->n_components == 1)
+ {
+ const double c_value = coefficient->value (cell->vertex(n));
+ for (unsigned int c=0; c<n_components; ++c)
+ coefficient_values(c) = c_value;
+ }
+ else
+ coefficient->vector_value(cell->vertex(n),
+ coefficient_values);
+ }
+
+
+ for (unsigned int s=0; s<n_solution_vectors; ++s)
+ for (unsigned int component=0; component<n_components; ++component)
+ if (component_mask[component] == true)
+ {
+ // get gradient here. [0] means x-derivative (there is no
+ // other component in 1d)
+ const double grad_here = gradients_here[s][n][component][0];
+
+ const double jump = ((grad_here - grad_neighbor[s](component)) *
+ coefficient_values(component));
+ (*errors[s])(cell_index) += jump*jump * cell->diameter();
+ }
+ }
+
+ for (unsigned int s=0; s<n_solution_vectors; ++s)
+ (*errors[s])(cell_index) = std::sqrt((*errors[s])(cell_index));
+ }
+}
+
+
+// explicit instantiations
+#include "error_estimator_1d.inst"
+
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $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.
+//
+// ---------------------------------------------------------------------
+
+
+for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; DH : DOFHANDLER_TEMPLATES )
+{
+#if deal_II_dimension == 1 && deal_II_dimension <= deal_II_space_dimension
+
+template
+void
+KellyErrorEstimator<deal_II_dimension, deal_II_space_dimension>::
+estimate<VEC,DH<deal_II_dimension,deal_II_space_dimension> > (const Mapping<deal_II_dimension, deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const Quadrature<deal_II_dimension-1> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ const VEC &,
+ Vector<float> &,
+ const ComponentMask &,
+ const Function<deal_II_space_dimension> *,
+ const unsigned int ,
+ const unsigned int ,
+ const types::material_id);
+
+template
+void
+KellyErrorEstimator<deal_II_dimension, deal_II_space_dimension>::
+estimate<VEC,DH<deal_II_dimension,deal_II_space_dimension> > (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const Quadrature<deal_II_dimension-1> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ const VEC &,
+ Vector<float> &,
+ const ComponentMask &,
+ const Function<deal_II_space_dimension> *,
+ const unsigned int ,
+ const unsigned int ,
+ const types::material_id);
+
+template
+void
+KellyErrorEstimator<deal_II_dimension, deal_II_space_dimension>::
+estimate<VEC,DH<deal_II_dimension,deal_II_space_dimension> > (const Mapping<deal_II_dimension, deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const Quadrature<deal_II_dimension-1> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ const std::vector<const VEC *> &,
+ std::vector<Vector<float> *> &,
+ const ComponentMask &,
+ const Function<deal_II_space_dimension> *,
+ const unsigned int ,
+ const unsigned int ,
+ const types::material_id);
+
+template
+void
+KellyErrorEstimator<deal_II_dimension, deal_II_space_dimension>::
+estimate<VEC,DH<deal_II_dimension,deal_II_space_dimension> > (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const Quadrature<deal_II_dimension-1> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ const std::vector<const VEC *> &,
+ std::vector<Vector<float> *> &,
+ const ComponentMask &,
+ const Function<deal_II_space_dimension> *,
+ const unsigned int ,
+ const unsigned int ,
+ const types::material_id);
+
+template
+void
+KellyErrorEstimator<deal_II_dimension, deal_II_space_dimension>::
+estimate<VEC,DH<deal_II_dimension,deal_II_space_dimension> > (const Mapping<deal_II_dimension, deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const hp::QCollection<deal_II_dimension-1> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ const VEC &,
+ Vector<float> &,
+ const ComponentMask &,
+ const Function<deal_II_space_dimension> *,
+ const unsigned int ,
+ const unsigned int ,
+ const types::material_id);
+
+template
+void
+KellyErrorEstimator<deal_II_dimension, deal_II_space_dimension>::
+estimate<VEC,DH<deal_II_dimension,deal_II_space_dimension> > (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const hp::QCollection<deal_II_dimension-1> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ const VEC &,
+ Vector<float> &,
+ const ComponentMask &,
+ const Function<deal_II_space_dimension> *,
+ const unsigned int ,
+ const unsigned int ,
+ const types::material_id);
+
+template
+void
+KellyErrorEstimator<deal_II_dimension, deal_II_space_dimension>::
+estimate<VEC,DH<deal_II_dimension,deal_II_space_dimension> > (const Mapping<deal_II_dimension, deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const hp::QCollection<deal_II_dimension-1> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ const std::vector<const VEC *> &,
+ std::vector<Vector<float> *> &,
+ const ComponentMask &,
+ const Function<deal_II_space_dimension> *,
+ const unsigned int ,
+ const unsigned int ,
+ const types::material_id);
+
+template
+void
+KellyErrorEstimator<deal_II_dimension, deal_II_space_dimension>::
+estimate<VEC,DH<deal_II_dimension,deal_II_space_dimension> > (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const hp::QCollection<deal_II_dimension-1> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ const std::vector<const VEC *> &,
+ std::vector<Vector<float> *> &,
+ const ComponentMask &,
+ const Function<deal_II_space_dimension> *,
+ const unsigned int ,
+ const unsigned int ,
+ const types::material_id);
+
+#endif
+}
{
matrices(i,j).reinit (fe[i].dofs_per_cell, fe[j].dofs_per_cell);
- // see if we can get the
- // interpolation matrices
- // for this combination
- // of elements. if not,
- // reset the matrix sizes
- // to zero to indicate
- // that this particular
- // combination isn't
- // supported. this isn't
- // an outright error
- // right away since we
- // may never need to
- // actually interpolate
- // between these two
- // elements on actual
- // cells; we simply have
- // to trigger an error if
- // someone actually tries
+ // see if we can get the interpolation matrices for this
+ // combination of elements. if not, reset the matrix sizes to zero
+ // to indicate that this particular combination isn't
+ // supported. this isn't an outright error right away since we may
+ // never need to actually interpolate between these two elements
+ // on actual cells; we simply have to trigger an error if someone
+ // actually tries
try
{
fe[i].get_interpolation_matrix (fe[j], matrices(i,j));
local_values.reinit (cell->has_children() ?
cell->child(0)->get_fe().dofs_per_cell
: cell->get_fe().dofs_per_cell, true);
- AssertDimension (local_values.size(),
- interpolation_hp(new_fe_index,old_index).m());
+ // do the interpolation. we get into trouble if the
+ // interpolation_hp(new,old) matrix hasn't been computed.
+ // this can happen if the respective elements don't support
+ // the corresponding interpolation; if that's the case, then
+ // the computation of the matrix simply sets the matrix
+ // back to size zero. so if we get here and that is
+ // the wrong size, then this may be because the elements
+ // haven't implemented the correct function yet
+ //
+ // there is one wrinkle. we would like to only error out if
+ // the size of the matrix is 0 times 0 but at least one
+ // of the elements has more than one dof per cell. the
+ // problem is that if you reinit a matrix to 4x0, it automatically
+ // sets its size to 0x0. so we can only execute the following
+ // test if *both* elements have dofs_per_cell>0, not if *at
+ // least one* have.
+ Assert (! ((interpolation_hp(new_fe_index,old_index).m() == 0)
+ &&
+ (interpolation_hp(new_fe_index,old_index).n() == 0)
+ &&
+ ((dof_handler->get_fe()[new_fe_index].dofs_per_cell > 0)
+ &&
+ (dof_handler->get_fe()[old_index].dofs_per_cell > 0))),
+ ExcMessage ("The interpolation between two different "
+ "elements you are trying to use here has "
+ "not been implemented for this pair of "
+ "elements!"));
+
// simple case where all children have the
// same FE index: just interpolate to their FE
// first and then use the standard routines
- interpolation_hp(new_fe_index,old_index).vmult (local_values, tmp);
+ if (tmp.size() > 0)
+ interpolation_hp(new_fe_index,old_index).vmult (local_values, tmp);
+ else
+ local_values = 0;
}
if (cell->has_children() == false)
AssertDimension (tmp.size(),
interpolation_hp(c_index,old_index).n());
local_values.reinit(cell->child(child)->get_fe().dofs_per_cell, true);
- AssertDimension (local_values.size(),
- interpolation_hp(c_index,old_index).m());
- interpolation_hp(c_index,old_index).vmult (local_values, tmp);
+
+ // do the interpolation. same problem as above
+ Assert (! ((interpolation_hp(c_index,old_index).m() == 0)
+ &&
+ (interpolation_hp(c_index,old_index).n() == 0)
+ &&
+ ((dof_handler->get_fe()[c_index].dofs_per_cell > 0)
+ &&
+ (dof_handler->get_fe()[old_index].dofs_per_cell > 0))),
+ ExcMessage ("The interpolation between two different "
+ "elements you are trying to use here has "
+ "not been implemented for this pair of "
+ "elements!"));
+
+ if (tmp.size() > 0)
+ interpolation_hp(c_index,old_index).vmult (local_values, tmp);
+ else
+ local_values = 0;
}
else
local_values = tmp;
#define DIM_B 2
#endif
+// This file compiles the first quarter of the instantiations from solution_transfer.cc
+// to reduce the compilation unit (and memory consumption)
#include "solution_transfer.inst"
DEAL_II_NAMESPACE_CLOSE
#if deal_II_dimension <= deal_II_space_dimension
#if (deal_II_space_dimension == DIM_A) || (deal_II_space_dimension == DIM_B)
+#ifndef INSTANTIATE_HP_DH
template class SolutionTransfer<deal_II_dimension, VEC, DoFHandler<deal_II_dimension, deal_II_space_dimension> >;
+#else
template class SolutionTransfer<deal_II_dimension, VEC, hp::DoFHandler<deal_II_dimension, deal_II_space_dimension> >;
#endif
#endif
+#endif
}
//
// ---------------------------------------------------------------------
-// This file compiles the second half of the instantiations from solution_transfer.cc
-// to get the memory consumption below 1.5gb with gcc (if compiling with PETSc and Trilinos).
+// This file compiles the second quarter of the instantiations from solution_transfer.cc
+// to reduce the compilation unit (and memory consumption)
+//#define INSTANTIATE_HP_DH
#define SOLUTION_TRANSFER_INSTANTIATE_PART_TWO
#include "solution_transfer.cc"
--- /dev/null
+// ---------------------------------------------------------------------
+// $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 file compiles the third quarter of the instantiations from solution_transfer.cc
+// to reduce the compilation unit (and memory consumption)
+
+#define INSTANTIATE_HP_DH
+//#define SOLUTION_TRANSFER_INSTANTIATE_PART_TWO
+
+#include "solution_transfer.cc"
--- /dev/null
+// ---------------------------------------------------------------------
+// $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 file compiles the fourth quarter of the instantiations from solution_transfer.cc
+// to reduce the compilation unit (and memory consumption)
+
+#define INSTANTIATE_HP_DH
+#define SOLUTION_TRANSFER_INSTANTIATE_PART_TWO
+
+#include "solution_transfer.cc"
+++ /dev/null
-// ---------------------------------------------------------------------
-// $Id$
-//
-// Copyright (C) 1998 - 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.
-//
-// ---------------------------------------------------------------------
-
-
-for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
- {
-#if deal_II_dimension <= deal_II_space_dimension
- namespace VectorTools \{
-
- template
- void integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_space_dimension>
- (const DoFHandler<deal_II_dimension, deal_II_space_dimension>&,
- const VEC&,
- const Function<deal_II_space_dimension>&,
- Vector<float>&,
- const Quadrature<deal_II_dimension>&,
- const NormType&,
- const Function<deal_II_space_dimension>*,
- const double);
-
- template
- void integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_space_dimension >
- (const DoFHandler<deal_II_dimension, deal_II_space_dimension>&,
- const VEC&,
- const Function<deal_II_space_dimension>&,
- Vector<double>&,
- const Quadrature<deal_II_dimension>&,
- const NormType&,
- const Function<deal_II_space_dimension>*,
- const double);
-
- template
- void integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_space_dimension>
- (const Mapping<deal_II_dimension, deal_II_space_dimension>&,
- const DoFHandler<deal_II_dimension, deal_II_space_dimension>&,
- const VEC&,
- const Function<deal_II_space_dimension>&,
- Vector<float>&,
- const Quadrature<deal_II_dimension>&,
- const NormType&,
- const Function<deal_II_space_dimension>*,
- const double);
-
- template
- void integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_space_dimension >
- (const Mapping<deal_II_dimension, deal_II_space_dimension>&,
- const DoFHandler<deal_II_dimension, deal_II_space_dimension>&,
- const VEC&,
- const Function<deal_II_space_dimension>&,
- Vector<double>&,
- const Quadrature<deal_II_dimension>&,
- const NormType&,
- const Function<deal_II_space_dimension>*,
- const double);
-
-
-
- template
- double compute_mean_value<deal_II_dimension>
- (const Mapping<deal_II_dimension,deal_II_space_dimension>&,
- const DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
- const Quadrature<deal_II_dimension>&,
- const VEC&,
- const unsigned int);
-
- template
- double compute_mean_value<deal_II_dimension>
- (const DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
- const Quadrature<deal_II_dimension>&,
- const VEC&,
- const unsigned int);
-
- template
- void interpolate
- (const Mapping<deal_II_dimension,deal_II_space_dimension>&,
- const DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
- const Function<deal_II_space_dimension>&,
- VEC&);
-
- template
- void interpolate
- (const DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
- const Function<deal_II_space_dimension>&,
- VEC&);
-
- template
- void project
- (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
- const DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
- const ConstraintMatrix &,
- const Quadrature<deal_II_dimension> &,
- const Function<deal_II_space_dimension> &,
- VEC &,
- const bool,
- const Quadrature<deal_II_dimension-1> &,
- const bool);
-
- template
- void project
- (const DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
- const ConstraintMatrix &,
- const Quadrature<deal_II_dimension> &,
- const Function<deal_II_space_dimension> &,
- VEC &,
- const bool,
- const Quadrature<deal_II_dimension-1> &,
- const bool);
-
- template
- void project
- (const hp::MappingCollection<deal_II_dimension,deal_II_space_dimension> &,
- const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
- const ConstraintMatrix &,
- const hp::QCollection<deal_II_dimension> &,
- const Function<deal_II_space_dimension> &,
- VEC &,
- const bool,
- const hp::QCollection<deal_II_dimension-1> &,
- const bool);
-
- template
- void project
- (const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
- const ConstraintMatrix &,
- const hp::QCollection<deal_II_dimension> &,
- const Function<deal_II_space_dimension> &,
- VEC &,
- const bool,
- const hp::QCollection<deal_II_dimension-1> &,
- const bool);
- \}
-#endif
- }
-
-
-
-//TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension, deal_II_space_dimension>
-// where applicable and move to codimension cases above also when applicable
-for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
- {
-#if deal_II_dimension == deal_II_space_dimension
-
- namespace VectorTools \{
-
- template
- void point_value<deal_II_dimension> (
- const hp::DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Point<deal_II_dimension>&,
- Vector<double>&);
-
- template
- void interpolate
- (const Mapping<deal_II_dimension>&,
- const hp::DoFHandler<deal_II_dimension>&,
- const Function<deal_II_dimension>&,
- VEC&);
- template
- void interpolate
- (const hp::DoFHandler<deal_II_dimension>&,
- const Function<deal_II_dimension>&,
- VEC&);
-
- template
- double point_value<deal_II_dimension> (
- const hp::DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Point<deal_II_dimension>&);
-
- template
- void point_value<deal_II_dimension> (
- const hp::MappingCollection<deal_II_dimension>&,
- const hp::DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Point<deal_II_dimension>&,
- Vector<double>&);
-
- template
- void interpolate
- (const DoFHandler<deal_II_dimension>&,
- const DoFHandler<deal_II_dimension>&,
- const FullMatrix<double>&,
- const VEC&,
- VEC&);
-
- template
- double point_value<deal_II_dimension> (
- const hp::MappingCollection<deal_II_dimension>&,
- const hp::DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Point<deal_II_dimension>&);
-
- template
- void integrate_difference<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Function<deal_II_dimension>&,
- Vector<double>&,
- const hp::QCollection<deal_II_dimension>&,
- const NormType&,
- const Function<deal_II_dimension>*,
- const double);
- template
- void integrate_difference<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Function<deal_II_dimension>&,
- Vector<float>&,
- const hp::QCollection<deal_II_dimension>&,
- const NormType&,
- const Function<deal_II_dimension>*,
- const double);
- template
- void integrate_difference<deal_II_dimension>
- (const hp::MappingCollection<deal_II_dimension>&,
- const hp::DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Function<deal_II_dimension>&,
- Vector<double>&,
- const hp::QCollection<deal_II_dimension>&,
- const NormType&,
- const Function<deal_II_dimension>*,
- const double);
- template
- void integrate_difference<deal_II_dimension>
- (const hp::MappingCollection<deal_II_dimension>&,
- const hp::DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Function<deal_II_dimension>&,
- Vector<float>&,
- const hp::QCollection<deal_II_dimension>&,
- const NormType&,
- const Function<deal_II_dimension>*,
- const double);
-
- template
- void point_difference<deal_II_dimension> (
- const DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Function<deal_II_dimension>&,
- Vector<double>&,
- const Point<deal_II_dimension>&);
-
- template
- void point_difference<deal_II_dimension> (
- const Mapping<deal_II_dimension>&,
- const DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Function<deal_II_dimension>&,
- Vector<double>&,
- const Point<deal_II_dimension>&);
-
- template
- void point_value<deal_II_dimension> (
- const DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Point<deal_II_dimension>&,
- Vector<double>&);
-
- template
- double point_value<deal_II_dimension> (
- const DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Point<deal_II_dimension>&);
-
- template
- void point_value<deal_II_dimension> (
- const Mapping<deal_II_dimension>&,
- const DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Point<deal_II_dimension>&,
- Vector<double>&);
-
- template
- double point_value<deal_II_dimension> (
- const Mapping<deal_II_dimension>&,
- const DoFHandler<deal_II_dimension>&,
- const VEC&,
- const Point<deal_II_dimension>&);
-
- \}
-#endif
- }
-
-
-for (VEC : SERIAL_VECTORS)
-{
- namespace VectorTools \{
- template
- void subtract_mean_value(VEC &, const std::vector<bool> &);
- \}
-}
-
-
-for (deal_II_dimension : DIMENSIONS)
-{
- namespace VectorTools \{
- template
- void interpolate_boundary_values (
- const MGDoFHandler<deal_II_dimension> &,
- const types::boundary_id,
- const Function<deal_II_dimension> &,
- ConstraintMatrix&,
- const ComponentMask &);
-
- template
- void interpolate_boundary_values (
- const MGDoFHandler<deal_II_dimension> &,
- const types::boundary_id,
- const Function<deal_II_dimension> &,
- std::map<types::global_dof_index,double> &,
- const ComponentMask &);
- \}
-}
-
-
-for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; DH : DOFHANDLER_TEMPLATES)
- {
-#if deal_II_dimension <= deal_II_space_dimension
- namespace VectorTools \{
- template
- void interpolate_boundary_values
- (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
- const DH<deal_II_dimension,deal_II_space_dimension> &,
- const FunctionMap<deal_II_space_dimension>::type &,
- std::map<types::global_dof_index,double> &,
- const ComponentMask &);
-
- template
- void interpolate_boundary_values
- (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
- const DH<deal_II_dimension,deal_II_space_dimension> &,
- const types::boundary_id,
- const Function<deal_II_space_dimension> &,
- std::map<types::global_dof_index,double> &,
- const ComponentMask &);
-
- template
- void interpolate_boundary_values (
- const DH<deal_II_dimension,deal_II_space_dimension> &,
- const types::boundary_id,
- const Function<deal_II_space_dimension> &,
- std::map<types::global_dof_index,double> &,
- const ComponentMask &);
-
- template
- void interpolate_boundary_values
- (const DH<deal_II_dimension,deal_II_space_dimension> &,
- const FunctionMap<deal_II_space_dimension>::type &,
- std::map<types::global_dof_index,double> &,
- const ComponentMask &);
-
- template
- void interpolate_boundary_values (
- const Mapping<deal_II_dimension,deal_II_space_dimension> &,
- const DH<deal_II_dimension,deal_II_space_dimension> &,
- const FunctionMap<deal_II_space_dimension>::type &,
- ConstraintMatrix &,
- const ComponentMask &);
-
- template
- void interpolate_boundary_values
- (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
- const DH<deal_II_dimension,deal_II_space_dimension> &,
- const types::boundary_id,
- const Function<deal_II_space_dimension> &,
- ConstraintMatrix &,
- const ComponentMask &);
-
- template
- void interpolate_boundary_values (
- const DH<deal_II_dimension,deal_II_space_dimension> &,
- const types::boundary_id,
- const Function<deal_II_space_dimension> &,
- ConstraintMatrix &,
- const ComponentMask &);
-
- template
- void interpolate_boundary_values (
- const DH<deal_II_dimension,deal_II_space_dimension> &,
- const FunctionMap<deal_II_space_dimension>::type &,
- ConstraintMatrix &,
- const ComponentMask &);
-
- \}
-#endif
- }
-
-
-for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
- {
-#if deal_II_dimension <= deal_II_space_dimension
- namespace VectorTools \{
- template
- void create_right_hand_side<deal_II_dimension,deal_II_space_dimension>
- (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
- const DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
- const Quadrature<deal_II_dimension> &,
- const Function<deal_II_space_dimension> &,
- Vector<double> &);
-
- template
- void create_right_hand_side<deal_II_dimension,deal_II_space_dimension>
- (const DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
- const Quadrature<deal_II_dimension> &,
- const Function<deal_II_space_dimension> &,
- Vector<double> &);
-
- \}
-#endif
- }
-
-//TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension, deal_II_space_dimension>
-// where applicable and move to codimension cases above also when applicable
-for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
- {
- namespace VectorTools \{
-
-#if deal_II_dimension <= deal_II_space_dimension
- template
- void project_boundary_values<deal_II_dimension,deal_II_space_dimension>
- (const hp::MappingCollection<deal_II_dimension,deal_II_space_dimension> &,
- const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
- const FunctionMap<deal_II_space_dimension>::type &,
- const hp::QCollection<deal_II_dimension-1>&,
- std::map<types::global_dof_index,double>&,
- std::vector<unsigned int>);
-
- template
- void project_boundary_values<deal_II_dimension,deal_II_space_dimension>
- (const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
- const FunctionMap<deal_II_space_dimension>::type &,
- const hp::QCollection<deal_II_dimension-1>&,
- std::map<types::global_dof_index,double>&,
- std::vector<unsigned int>);
-#endif
-
-#if deal_II_dimension == deal_II_space_dimension
- template
- void create_right_hand_side<deal_II_dimension>
- (const hp::MappingCollection<deal_II_dimension> &,
- const hp::DoFHandler<deal_II_dimension> &,
- const hp::QCollection<deal_II_dimension> &,
- const Function<deal_II_dimension> &,
- Vector<double> &);
-
- template
- void create_right_hand_side<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension> &,
- const hp::QCollection<deal_II_dimension> &,
- const Function<deal_II_dimension> &,
- Vector<double> &);
-
- template
- void create_point_source_vector<deal_II_dimension>
- (const Mapping<deal_II_dimension> &,
- const DoFHandler<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- Vector<double> &);
- template
- void create_point_source_vector<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- Vector<double> &);
-
- template
- void create_point_source_vector<deal_II_dimension>
- (const hp::MappingCollection<deal_II_dimension> &,
- const hp::DoFHandler<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- Vector<double> &);
- template
- void create_point_source_vector<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- Vector<double> &);
- template
- void create_point_source_vector<deal_II_dimension>
- (const Mapping<deal_II_dimension> &,
- const DoFHandler<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- Vector<double> &);
- template
- void create_point_source_vector<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- Vector<double> &);
-
- template
- void create_point_source_vector<deal_II_dimension>
- (const hp::MappingCollection<deal_II_dimension> &,
- const hp::DoFHandler<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- Vector<double> &);
- template
- void create_point_source_vector<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- const Point<deal_II_dimension> &,
- Vector<double> &);
-
-#if deal_II_dimension > 1
- template
- void
- create_boundary_right_hand_side<deal_II_dimension>
- (const Mapping<deal_II_dimension> &,
- const DoFHandler<deal_II_dimension> &,
- const Quadrature<deal_II_dimension-1> &,
- const Function<deal_II_dimension> &,
- Vector<double> &,
- const std::set<types::boundary_id> &);
-#endif
-
- template
- void
- create_boundary_right_hand_side<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &,
- const Quadrature<deal_II_dimension-1> &,
- const Function<deal_II_dimension> &,
- Vector<double> &,
- const std::set<types::boundary_id> &);
-
-#if deal_II_dimension > 1
- template
- void
- create_boundary_right_hand_side<deal_II_dimension>
- (const hp::MappingCollection<deal_II_dimension> &,
- const hp::DoFHandler<deal_II_dimension> &,
- const hp::QCollection<deal_II_dimension-1> &,
- const Function<deal_II_dimension> &,
- Vector<double> &,
- const std::set<types::boundary_id> &);
-#endif
-
- template
- void
- create_boundary_right_hand_side<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension> &,
- const hp::QCollection<deal_II_dimension-1> &,
- const Function<deal_II_dimension> &,
- Vector<double> &,
- const std::set<types::boundary_id> &);
-
-
-
-
-
- template
- void project_boundary_values<deal_II_dimension>
- (const Mapping<deal_II_dimension> &,
- const DoFHandler<deal_II_dimension> &,
- const FunctionMap<deal_II_dimension>::type &,
- const Quadrature<deal_II_dimension-1>&,
- std::map<types::global_dof_index,double>&, std::vector<unsigned int>);
-
- template
- void project_boundary_values<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &,
- const FunctionMap<deal_II_dimension>::type &,
- const Quadrature<deal_II_dimension-1>&,
- std::map<types::global_dof_index,double>&,
- std::vector<unsigned int>);
-
- template
- void project_boundary_values<deal_II_dimension>
- (const Mapping<deal_II_dimension> &,
- const DoFHandler<deal_II_dimension> &,
- const FunctionMap<deal_II_dimension>::type &,
- const Quadrature<deal_II_dimension-1>&,
- ConstraintMatrix&, std::vector<unsigned int>);
-
- template
- void project_boundary_values<deal_II_dimension>
- (const DoFHandler<deal_II_dimension> &,
- const FunctionMap<deal_II_dimension>::type &,
- const Quadrature<deal_II_dimension-1>&,
- ConstraintMatrix&,
- std::vector<unsigned int>);
-
-
-
-#if deal_II_dimension != 1
- template
- void project_boundary_values_curl_conforming<deal_II_dimension>
- (const DoFHandler<deal_II_dimension>&,
- const unsigned int,
- const Function<deal_II_dimension>&,
- const types::boundary_id,
- ConstraintMatrix&,
- const Mapping<deal_II_dimension>&);
- template
- void project_boundary_values_curl_conforming<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension>&,
- const unsigned int,
- const Function<deal_II_dimension>&,
- const types::boundary_id,
- ConstraintMatrix&,
- const hp::MappingCollection<deal_II_dimension>&);
- template
- void project_boundary_values_div_conforming<deal_II_dimension>
- (const DoFHandler<deal_II_dimension>&,
- const unsigned int,
- const Function<deal_II_dimension>&,
- const types::boundary_id,
- ConstraintMatrix&,
- const Mapping<deal_II_dimension>&);
- template
- void project_boundary_values_div_conforming<deal_II_dimension>
- (const hp::DoFHandler<deal_II_dimension>&,
- const unsigned int,
- const Function<deal_II_dimension>&,
- const types::boundary_id,
- ConstraintMatrix&,
- const hp::MappingCollection<deal_II_dimension>&);
- template
- void
- compute_no_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
- const unsigned int first_vector_component,
- const std::set<types::boundary_id> &boundary_ids,
- ConstraintMatrix &constraints,
- const Mapping<deal_II_dimension> &mapping);
- template
- void
- compute_no_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
- const unsigned int first_vector_component,
- const std::set<types::boundary_id> &boundary_ids,
- ConstraintMatrix &constraints,
- const Mapping<deal_II_dimension> &mapping);
-#endif
-#endif
- \}
- }
-
-
-
-for (deal_II_dimension : DIMENSIONS)
-{
- namespace VectorTools \{
-
- template
- void interpolate_to_different_mesh
- (const DoFHandler<deal_II_dimension> &,
- const Vector<float> &,
- const DoFHandler<deal_II_dimension> &,
- Vector<float> &);
-
- template
- void interpolate_to_different_mesh
- (const DoFHandler<deal_II_dimension> &,
- const Vector<float> &,
- const DoFHandler<deal_II_dimension> &,
- const ConstraintMatrix &,
- Vector<float> &);
-
- template
- void interpolate_to_different_mesh
- (const InterGridMap<DoFHandler<deal_II_dimension> > &,
- const Vector<float> &,
- const ConstraintMatrix &,
- Vector<float> &);
-
- template
- void interpolate_to_different_mesh
- (const DoFHandler<deal_II_dimension> &,
- const Vector<double> &,
- const DoFHandler<deal_II_dimension> &,
- Vector<double> &);
-
- template
- void interpolate_to_different_mesh
- (const DoFHandler<deal_II_dimension> &,
- const Vector<double> &,
- const DoFHandler<deal_II_dimension> &,
- const ConstraintMatrix &,
- Vector<double> &);
-
- template
- void interpolate_to_different_mesh
- (const InterGridMap<DoFHandler<deal_II_dimension> > &,
- const Vector<double> &,
- const ConstraintMatrix &,
- Vector<double> &);
-
- \}
-}
-
-
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/numerics/vector_tools.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+// ---------------------------- explicit instantiations --------------------
+#include "vector_tools_boundary.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+for (deal_II_dimension : DIMENSIONS)
+{
+ namespace VectorTools \{
+ template
+ void interpolate_boundary_values (
+ const MGDoFHandler<deal_II_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_dimension> &,
+ ConstraintMatrix&,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const MGDoFHandler<deal_II_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_dimension> &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+ \}
+}
+
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; DH : DOFHANDLER_TEMPLATES)
+ {
+#if deal_II_dimension <= deal_II_space_dimension
+ namespace VectorTools \{
+ template
+ void interpolate_boundary_values
+ (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values
+ (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_space_dimension> &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_space_dimension> &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values
+ (const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values
+ (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_space_dimension> &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_space_dimension> &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+ \}
+#endif
+}
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+ namespace VectorTools \{
+#if deal_II_dimension == deal_II_space_dimension
+
+ template
+ void project_boundary_values<deal_II_dimension>
+ (const Mapping<deal_II_dimension> &,
+ const DoFHandler<deal_II_dimension> &,
+ const FunctionMap<deal_II_dimension>::type &,
+ const Quadrature<deal_II_dimension-1>&,
+ std::map<types::global_dof_index,double>&, std::vector<unsigned int>);
+
+ template
+ void project_boundary_values<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &,
+ const FunctionMap<deal_II_dimension>::type &,
+ const Quadrature<deal_II_dimension-1>&,
+ std::map<types::global_dof_index,double>&,
+ std::vector<unsigned int>);
+
+ template
+ void project_boundary_values<deal_II_dimension>
+ (const Mapping<deal_II_dimension> &,
+ const DoFHandler<deal_II_dimension> &,
+ const FunctionMap<deal_II_dimension>::type &,
+ const Quadrature<deal_II_dimension-1>&,
+ ConstraintMatrix&, std::vector<unsigned int>);
+
+ template
+ void project_boundary_values<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &,
+ const FunctionMap<deal_II_dimension>::type &,
+ const Quadrature<deal_II_dimension-1>&,
+ ConstraintMatrix&,
+ std::vector<unsigned int>);
+
+
+
+#if deal_II_dimension != 1
+ template
+ void project_boundary_values_curl_conforming<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension>&,
+ const unsigned int,
+ const Function<deal_II_dimension>&,
+ const types::boundary_id,
+ ConstraintMatrix&,
+ const Mapping<deal_II_dimension>&);
+ template
+ void project_boundary_values_curl_conforming<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension>&,
+ const unsigned int,
+ const Function<deal_II_dimension>&,
+ const types::boundary_id,
+ ConstraintMatrix&,
+ const hp::MappingCollection<deal_II_dimension>&);
+ template
+ void project_boundary_values_div_conforming<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension>&,
+ const unsigned int,
+ const Function<deal_II_dimension>&,
+ const types::boundary_id,
+ ConstraintMatrix&,
+ const Mapping<deal_II_dimension>&);
+ template
+ void project_boundary_values_div_conforming<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension>&,
+ const unsigned int,
+ const Function<deal_II_dimension>&,
+ const types::boundary_id,
+ ConstraintMatrix&,
+ const hp::MappingCollection<deal_II_dimension>&);
+#endif
+#endif
+ \}
+ }
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/numerics/vector_tools.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+// ---------------------------- explicit instantiations --------------------
+#include "vector_tools_constraints.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+//TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension, deal_II_space_dimension>
+// where applicable and move to codimension cases above also when applicable
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+ namespace VectorTools \{
+
+#if deal_II_dimension == deal_II_space_dimension
+#if deal_II_dimension != 1
+ template
+ void
+ compute_no_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+ template
+ void
+ compute_no_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+
+ template
+ void
+ compute_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+ template
+ void
+ compute_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+#endif
+#endif
+ \}
+ }
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/numerics/vector_tools.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+// ---------------------------- explicit instantiations --------------------
+#include "vector_tools_integrate_difference.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+#if deal_II_dimension <= deal_II_space_dimension
+ namespace VectorTools \{
+
+ template
+ void integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_space_dimension>
+ (const Mapping<deal_II_dimension, deal_II_space_dimension>&,
+ const DoFHandler<deal_II_dimension, deal_II_space_dimension>&,
+ const VEC&,
+ const Function<deal_II_space_dimension>&,
+ Vector<float>&,
+ const Quadrature<deal_II_dimension>&,
+ const NormType&,
+ const Function<deal_II_space_dimension>*,
+ const double);
+
+ template
+ void integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_space_dimension>
+ (const DoFHandler<deal_II_dimension, deal_II_space_dimension>&,
+ const VEC&,
+ const Function<deal_II_space_dimension>&,
+ Vector<float>&,
+ const Quadrature<deal_II_dimension>&,
+ const NormType&,
+ const Function<deal_II_space_dimension>*,
+ const double);
+
+ template
+ void integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_space_dimension >
+ (const Mapping<deal_II_dimension, deal_II_space_dimension>&,
+ const DoFHandler<deal_II_dimension, deal_II_space_dimension>&,
+ const VEC&,
+ const Function<deal_II_space_dimension>&,
+ Vector<double>&,
+ const Quadrature<deal_II_dimension>&,
+ const NormType&,
+ const Function<deal_II_space_dimension>*,
+ const double);
+
+ template
+ void integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_space_dimension >
+ (const DoFHandler<deal_II_dimension, deal_II_space_dimension>&,
+ const VEC&,
+ const Function<deal_II_space_dimension>&,
+ Vector<double>&,
+ const Quadrature<deal_II_dimension>&,
+ const NormType&,
+ const Function<deal_II_space_dimension>*,
+ const double);
+
+ template
+ void integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_space_dimension>
+ (const hp::MappingCollection<deal_II_dimension,deal_II_space_dimension>&,
+ const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
+ const VEC&,
+ const Function<deal_II_space_dimension>&,
+ Vector<double>&,
+ const hp::QCollection<deal_II_dimension>&,
+ const NormType&,
+ const Function<deal_II_space_dimension>*,
+ const double);
+
+ template
+ void integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_space_dimension>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
+ const VEC&,
+ const Function<deal_II_space_dimension>&,
+ Vector<double>&,
+ const hp::QCollection<deal_II_dimension>&,
+ const NormType&,
+ const Function<deal_II_space_dimension>*,
+ const double);
+
+ template
+ void integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_space_dimension>
+ (const hp::MappingCollection<deal_II_dimension,deal_II_space_dimension>&,
+ const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
+ const VEC&,
+ const Function<deal_II_space_dimension>&,
+ Vector<float>&,
+ const hp::QCollection<deal_II_dimension>&,
+ const NormType&,
+ const Function<deal_II_space_dimension>*,
+ const double);
+
+ template
+ void integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_space_dimension>
+ (const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
+ const VEC&,
+ const Function<deal_II_space_dimension>&,
+ Vector<float>&,
+ const hp::QCollection<deal_II_dimension>&,
+ const NormType&,
+ const Function<deal_II_space_dimension>*,
+ const double);
+
+ \}
+#endif
+ }
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/numerics/vector_tools.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+// ---------------------------- explicit instantiations --------------------
+#include "vector_tools_interpolate.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+#if deal_II_dimension <= deal_II_space_dimension
+ namespace VectorTools \{
+
+ template
+ void interpolate
+ (const Mapping<deal_II_dimension,deal_II_space_dimension>&,
+ const DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
+ const Function<deal_II_space_dimension>&,
+ VEC&);
+
+ template
+ void interpolate
+ (const DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
+ const Function<deal_II_space_dimension>&,
+ VEC&);
+ \}
+#endif
+ }
+
+
+
+//TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension, deal_II_space_dimension>
+// where applicable and move to codimension cases above also when applicable
+for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+#if deal_II_dimension == deal_II_space_dimension
+
+ namespace VectorTools \{
+
+ template
+ void interpolate
+ (const Mapping<deal_II_dimension>&,
+ const hp::DoFHandler<deal_II_dimension>&,
+ const Function<deal_II_dimension>&,
+ VEC&);
+ template
+ void interpolate
+ (const hp::DoFHandler<deal_II_dimension>&,
+ const Function<deal_II_dimension>&,
+ VEC&);
+
+ template
+ void interpolate
+ (const DoFHandler<deal_II_dimension>&,
+ const DoFHandler<deal_II_dimension>&,
+ const FullMatrix<double>&,
+ const VEC&,
+ VEC&);
+ \}
+#endif
+ }
+
+
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; DH : DOFHANDLER_TEMPLATES)
+ {
+#if deal_II_dimension <= deal_II_space_dimension
+ namespace VectorTools \{
+ template
+ void interpolate_boundary_values
+ (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values
+ (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_space_dimension> &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_space_dimension> &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values
+ (const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ std::map<types::global_dof_index,double> &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values
+ (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_space_dimension> &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const types::boundary_id,
+ const Function<deal_II_space_dimension> &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+ template
+ void interpolate_boundary_values (
+ const DH<deal_II_dimension,deal_II_space_dimension> &,
+ const FunctionMap<deal_II_space_dimension>::type &,
+ ConstraintMatrix &,
+ const ComponentMask &);
+
+ \}
+#endif
+ }
+
+
+
+for (deal_II_dimension : DIMENSIONS)
+{
+ namespace VectorTools \{
+
+ template
+ void interpolate_to_different_mesh
+ (const DoFHandler<deal_II_dimension> &,
+ const Vector<float> &,
+ const DoFHandler<deal_II_dimension> &,
+ Vector<float> &);
+
+ template
+ void interpolate_to_different_mesh
+ (const DoFHandler<deal_II_dimension> &,
+ const Vector<float> &,
+ const DoFHandler<deal_II_dimension> &,
+ const ConstraintMatrix &,
+ Vector<float> &);
+
+ template
+ void interpolate_to_different_mesh
+ (const InterGridMap<DoFHandler<deal_II_dimension> > &,
+ const Vector<float> &,
+ const ConstraintMatrix &,
+ Vector<float> &);
+
+ template
+ void interpolate_to_different_mesh
+ (const DoFHandler<deal_II_dimension> &,
+ const Vector<double> &,
+ const DoFHandler<deal_II_dimension> &,
+ Vector<double> &);
+
+ template
+ void interpolate_to_different_mesh
+ (const DoFHandler<deal_II_dimension> &,
+ const Vector<double> &,
+ const DoFHandler<deal_II_dimension> &,
+ const ConstraintMatrix &,
+ Vector<double> &);
+
+ template
+ void interpolate_to_different_mesh
+ (const InterGridMap<DoFHandler<deal_II_dimension> > &,
+ const Vector<double> &,
+ const ConstraintMatrix &,
+ Vector<double> &);
+
+ \}
+}
+
+
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/numerics/vector_tools.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+// ---------------------------- explicit instantiations --------------------
+#include "vector_tools_mean_value.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+#if deal_II_dimension <= deal_II_space_dimension
+ namespace VectorTools \{
+
+ template
+ double compute_mean_value<deal_II_dimension>
+ (const Mapping<deal_II_dimension,deal_II_space_dimension>&,
+ const DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
+ const Quadrature<deal_II_dimension>&,
+ const VEC&,
+ const unsigned int);
+
+ template
+ double compute_mean_value<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension,deal_II_space_dimension>&,
+ const Quadrature<deal_II_dimension>&,
+ const VEC&,
+ const unsigned int);
+
+ \}
+#endif
+ }
+
+
+
+for (VEC : SERIAL_VECTORS)
+{
+ namespace VectorTools \{
+ template
+ void subtract_mean_value(VEC &, const std::vector<bool> &);
+ \}
+}
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/numerics/vector_tools.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+// ---------------------------- explicit instantiations --------------------
+#include "vector_tools_point_value.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+//TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension, deal_II_space_dimension>
+// where applicable and move to codimension cases above also when applicable
+for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+#if deal_II_dimension == deal_II_space_dimension
+
+ namespace VectorTools \{
+
+ template
+ void point_value<deal_II_dimension> (
+ const hp::DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Point<deal_II_dimension>&,
+ Vector<double>&);
+
+ template
+ double point_value<deal_II_dimension> (
+ const hp::DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Point<deal_II_dimension>&);
+
+ template
+ void point_value<deal_II_dimension> (
+ const hp::MappingCollection<deal_II_dimension>&,
+ const hp::DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Point<deal_II_dimension>&,
+ Vector<double>&);
+
+ template
+ double point_value<deal_II_dimension> (
+ const hp::MappingCollection<deal_II_dimension>&,
+ const hp::DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Point<deal_II_dimension>&);
+
+ template
+ void point_difference<deal_II_dimension> (
+ const DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Function<deal_II_dimension>&,
+ Vector<double>&,
+ const Point<deal_II_dimension>&);
+
+ template
+ void point_difference<deal_II_dimension> (
+ const Mapping<deal_II_dimension>&,
+ const DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Function<deal_II_dimension>&,
+ Vector<double>&,
+ const Point<deal_II_dimension>&);
+
+ template
+ void point_value<deal_II_dimension> (
+ const DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Point<deal_II_dimension>&,
+ Vector<double>&);
+
+ template
+ double point_value<deal_II_dimension> (
+ const DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Point<deal_II_dimension>&);
+
+ template
+ void point_value<deal_II_dimension> (
+ const Mapping<deal_II_dimension>&,
+ const DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Point<deal_II_dimension>&,
+ Vector<double>&);
+
+ template
+ double point_value<deal_II_dimension> (
+ const Mapping<deal_II_dimension>&,
+ const DoFHandler<deal_II_dimension>&,
+ const VEC&,
+ const Point<deal_II_dimension>&);
+
+ \}
+#endif
+ }
+
+
+
+//TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension, deal_II_space_dimension>
+// where applicable and move to codimension cases above also when applicable
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+ namespace VectorTools \{
+
+#if deal_II_dimension == deal_II_space_dimension
+
+ template
+ void create_point_source_vector<deal_II_dimension>
+ (const Mapping<deal_II_dimension> &,
+ const DoFHandler<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ Vector<double> &);
+ template
+ void create_point_source_vector<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ Vector<double> &);
+
+ template
+ void create_point_source_vector<deal_II_dimension>
+ (const hp::MappingCollection<deal_II_dimension> &,
+ const hp::DoFHandler<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ Vector<double> &);
+ template
+ void create_point_source_vector<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ Vector<double> &);
+ template
+ void create_point_source_vector<deal_II_dimension>
+ (const Mapping<deal_II_dimension> &,
+ const DoFHandler<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ Vector<double> &);
+ template
+ void create_point_source_vector<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ Vector<double> &);
+
+ template
+ void create_point_source_vector<deal_II_dimension>
+ (const hp::MappingCollection<deal_II_dimension> &,
+ const hp::DoFHandler<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ Vector<double> &);
+ template
+ void create_point_source_vector<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ const Point<deal_II_dimension> &,
+ Vector<double> &);
+#endif
+ \}
+ }
DEAL_II_NAMESPACE_OPEN
// ---------------------------- explicit instantiations --------------------
-#include "vector_tools.inst"
+#include "vector_tools_project.inst"
DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+#if deal_II_dimension <= deal_II_space_dimension
+ namespace VectorTools \{
+
+ template
+ void project
+ (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
+ const ConstraintMatrix &,
+ const Quadrature<deal_II_dimension> &,
+ const Function<deal_II_space_dimension> &,
+ VEC &,
+ const bool,
+ const Quadrature<deal_II_dimension-1> &,
+ const bool);
+
+ template
+ void project
+ (const DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
+ const ConstraintMatrix &,
+ const Quadrature<deal_II_dimension> &,
+ const Function<deal_II_space_dimension> &,
+ VEC &,
+ const bool,
+ const Quadrature<deal_II_dimension-1> &,
+ const bool);
+
+ template
+ void project
+ (const hp::MappingCollection<deal_II_dimension,deal_II_space_dimension> &,
+ const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
+ const ConstraintMatrix &,
+ const hp::QCollection<deal_II_dimension> &,
+ const Function<deal_II_space_dimension> &,
+ VEC &,
+ const bool,
+ const hp::QCollection<deal_II_dimension-1> &,
+ const bool);
+
+ template
+ void project
+ (const hp::DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
+ const ConstraintMatrix &,
+ const hp::QCollection<deal_II_dimension> &,
+ const Function<deal_II_space_dimension> &,
+ VEC &,
+ const bool,
+ const hp::QCollection<deal_II_dimension-1> &,
+ const bool);
+ \}
+#endif
+ }
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/numerics/vector_tools.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+namespace VectorTools
+{
+
+// separate implementation for 1D because otherwise we get linker errors since
+// (hp::)FEFaceValues<1> is not compiled
+ template <>
+ void
+ create_boundary_right_hand_side (const Mapping<1,1> &,
+ const DoFHandler<1,1> &,
+ const Quadrature<0> &,
+ const Function<1> &,
+ Vector<double> &,
+ const std::set<types::boundary_id> &)
+ {
+ Assert (false, ExcImpossibleInDim(1));
+ }
+
+
+
+ template <>
+ void
+ create_boundary_right_hand_side (const Mapping<1,2> &,
+ const DoFHandler<1,2> &,
+ const Quadrature<0> &,
+ const Function<2> &,
+ Vector<double> &,
+ const std::set<types::boundary_id> &)
+ {
+ Assert (false, ExcImpossibleInDim(1));
+ }
+
+
+
+ template <>
+ void
+ create_boundary_right_hand_side (const hp::MappingCollection<1,1> &,
+ const hp::DoFHandler<1,1> &,
+ const hp::QCollection<0> &,
+ const Function<1> &,
+ Vector<double> &,
+ const std::set<types::boundary_id> &)
+ {
+ Assert (false, ExcImpossibleInDim(1));
+ }
+
+
+
+ template <>
+ void
+ create_boundary_right_hand_side (const hp::MappingCollection<1,2> &,
+ const hp::DoFHandler<1,2> &,
+ const hp::QCollection<0> &,
+ const Function<2> &,
+ Vector<double> &,
+ const std::set<types::boundary_id> &)
+ {
+ Assert (false, ExcImpossibleInDim(1));
+ }
+}
+
+// ---------------------------- explicit instantiations --------------------
+#include "vector_tools_rhs.inst"
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+#if deal_II_dimension <= deal_II_space_dimension
+ namespace VectorTools \{
+ template
+ void create_right_hand_side<deal_II_dimension,deal_II_space_dimension>
+ (const Mapping<deal_II_dimension,deal_II_space_dimension> &,
+ const DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
+ const Quadrature<deal_II_dimension> &,
+ const Function<deal_II_space_dimension> &,
+ Vector<double> &);
+
+ template
+ void create_right_hand_side<deal_II_dimension,deal_II_space_dimension>
+ (const DoFHandler<deal_II_dimension,deal_II_space_dimension> &,
+ const Quadrature<deal_II_dimension> &,
+ const Function<deal_II_space_dimension> &,
+ Vector<double> &);
+
+ \}
+#endif
+ }
+
+//TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension, deal_II_space_dimension>
+// where applicable and move to codimension cases above also when applicable
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+ {
+ namespace VectorTools \{
+
+#if deal_II_dimension == deal_II_space_dimension
+ template
+ void create_right_hand_side<deal_II_dimension>
+ (const hp::MappingCollection<deal_II_dimension> &,
+ const hp::DoFHandler<deal_II_dimension> &,
+ const hp::QCollection<deal_II_dimension> &,
+ const Function<deal_II_dimension> &,
+ Vector<double> &);
+
+ template
+ void create_right_hand_side<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension> &,
+ const hp::QCollection<deal_II_dimension> &,
+ const Function<deal_II_dimension> &,
+ Vector<double> &);
+
+#if deal_II_dimension > 1
+ template
+ void
+ create_boundary_right_hand_side<deal_II_dimension>
+ (const Mapping<deal_II_dimension> &,
+ const DoFHandler<deal_II_dimension> &,
+ const Quadrature<deal_II_dimension-1> &,
+ const Function<deal_II_dimension> &,
+ Vector<double> &,
+ const std::set<types::boundary_id> &);
+#endif
+
+ template
+ void
+ create_boundary_right_hand_side<deal_II_dimension>
+ (const DoFHandler<deal_II_dimension> &,
+ const Quadrature<deal_II_dimension-1> &,
+ const Function<deal_II_dimension> &,
+ Vector<double> &,
+ const std::set<types::boundary_id> &);
+
+#if deal_II_dimension > 1
+ template
+ void
+ create_boundary_right_hand_side<deal_II_dimension>
+ (const hp::MappingCollection<deal_II_dimension> &,
+ const hp::DoFHandler<deal_II_dimension> &,
+ const hp::QCollection<deal_II_dimension-1> &,
+ const Function<deal_II_dimension> &,
+ Vector<double> &,
+ const std::set<types::boundary_id> &);
+#endif
+
+ template
+ void
+ create_boundary_right_hand_side<deal_II_dimension>
+ (const hp::DoFHandler<deal_II_dimension> &,
+ const hp::QCollection<deal_II_dimension-1> &,
+ const Function<deal_II_dimension> &,
+ Vector<double> &,
+ const std::set<types::boundary_id> &);
+
+
+#endif
+ \}
+ }