pax_global_header00006660000000000000000000000064131331443110014504gustar00rootroot0000000000000052 comment=c3267259cb0d75ac585f31e034f1b64fee672fe0 dune-localfunctions-2.5.1/000077500000000000000000000000001313314431100154655ustar00rootroot00000000000000dune-localfunctions-2.5.1/.gitignore000066400000000000000000000000141313314431100174500ustar00rootroot00000000000000*~ /build*/ dune-localfunctions-2.5.1/.gitlab-ci.yml000066400000000000000000000013711313314431100201230ustar00rootroot00000000000000--- variables: DUNECI_BRANCH: releases/2.5 before_script: - duneci-install-module https://gitlab.dune-project.org/core/dune-common.git - duneci-install-module https://gitlab.dune-project.org/core/dune-geometry.git debian:9--gcc: image: duneci/base:9 script: duneci-standard-test debian:9--clang: image: duneci/base:9 script: duneci-standard-test --opts=/duneci/opts.clang debian:8--gcc: image: duneci/base:8 script: duneci-standard-test debian:8-backports--clang: image: duneci/base:8-backports script: duneci-standard-test --opts=/duneci/opts.clang ubuntu:16.04--gcc: image: duneci/base:16.04 script: duneci-standard-test ubuntu:16.04--clang: image: duneci/base:16.04 script: duneci-standard-test --opts=/duneci/opts.clang dune-localfunctions-2.5.1/CMakeLists.txt000066400000000000000000000013471313314431100202320ustar00rootroot00000000000000# set up project project("dune-localfunctions" C CXX) # general stuff cmake_minimum_required(VERSION 2.8.12) # guess dune-common build dir if(NOT (dune-common_DIR OR dune-common_ROOT OR "${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*")) string(REPLACE ${CMAKE_PROJECT_NAME} dune-common dune-common_DIR ${PROJECT_BINARY_DIR}) endif() #find dune-common and set the module path find_package(dune-common REQUIRED) list(APPEND CMAKE_MODULE_PATH ${dune-common_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/modules") #include the dune macros include(DuneMacros) # start a dune project with information from dune.module dune_project() add_subdirectory(doc) add_subdirectory(dune) finalize_dune_project(GENERATE_CONFIG_H_CMAKE) dune-localfunctions-2.5.1/COPYING000077700000000000000000000000001313314431100201172LICENSE.mdustar00rootroot00000000000000dune-localfunctions-2.5.1/INSTALL000066400000000000000000000046621313314431100165260ustar00rootroot00000000000000Installation Instructions ========================= For a full explanation of the DUNE installation process please read the installation notes [0]. The following introduction is meant for the impatient. Getting started --------------- Suppose you have downloaded all DUNE modules of interest to your computer and extracted then in one common directory. See [1] for a list of available modules. To compile the modules Dune has to check several components of your system and whether prerequisites within the modules are met. For the ease of users we have designed a custom build system on top of CMake. Run ./dune-common/bin/dunecontrol all to commence those tests and build all modules you have downloaded. Don't worry about messages telling you that libraries are missing: they are only needed for grid-self-checks we need for developing. You can customize the build to your specific needs by using an options file (see below) ./dune-common/bin/dunecontrol --opts=/path_to/file.opts If you did not tell dunecontrol to install with an options file you need to run ./dune-common/bin/dunecontrol make install to install Dune (you may need root-permissions for the install part depending on the prefix set) A more comprehensive introduction to the build system can be found in [0]. Passing options to the build process ------------------------------------ Using the dunecontrol script the following atomic commands can be executed: - configure (runs the CMake configuration tests for each module) - exec (executes a command in each module source directory) - bexec (executes a command in each module build directory) - make (builds each module) - update (updates the Git or Subversion version) The composite command all simply runs configure and make for each module. As it is often not convenient to specify the desired options after the duncontroll call, one can pass the options via a file specified by the --opts= option. Specify the options via the variable CMAKE_FLAGS= An example of an options file is # use a special compiler (g++ version 5.0), # install to a custom directory, default is /usr/local/bin, # disable the external library SuperLU, # and use Ninja-build instead of make as the build-tool CMAKE_FLAGS="-DCMAKE_CXX_COMPILER=g++-5 -DCMAKE_INSTALL_PREFIX='/tmp/HuHu' -DCMAKE_DISABLE_FIND_PACKAGE_SuperLU=true -GNinja" Links ----- 0. https://www.dune-project.org/doc/installation 1. https://dune-project.org/releases dune-localfunctions-2.5.1/LICENSE.md000066400000000000000000000471231313314431100171000ustar00rootroot00000000000000Copyright holders: 2015--2016 Marco Agnese 2008--2010 Peter Bastian 2015 Timo Betcke 2009--2014 Markus Blatt 2016 Lukas Böger 2014 Andreas Buhr 2014--2016 Ansgar Burchardt 2009--2013 Andreas Dedner 2010 Martin Drohmann 2008--2015 Christian Engwer 2008--2016 Jorrit Fahlke 2011--2013 Bernd Flemisch 2015 Elisa Friebel 2012 Christoph Gersbacher 2009--2016 Carsten Gräser 2015--2016 Felix Gruber 2011--2016 Christoph Grüninger 2013 Guillaume Jouvet 2015--2016 Dominic Kempf 2015 Angela Klewinghaus 2014 Arne Morten Kvarving 2015 Jizhou Li 2013--2016 Tobias Malkmus 2009 Sven Marnach 2013--2016 Steffen Müthing 2012 Rebecca Neumann 2008--2016 Martin Nolte 2011--2016 Elias Pipping 2016 Simon Praetorius 2012--2013 Human Rezaijafari 2011--2012 Uli Sack 2008--2016 Oliver Sander 2011--2012 Matthias Wohlmuth 2010--2015 Jonathan Youett The DUNE library and headers are licensed under version 2 of the GNU General Public License (see below), with a special exception for linking and compiling against DUNE, the so-called "runtime exception." The license is intended to be similar to the GNU Lesser General Public License, which by itself isn't suitable for a template library. The exact wording of the exception reads as follows: As a special exception, you may use the DUNE source files as part of a software library or application without restriction. Specifically, if other files instantiate templates or use macros or inline functions from one or more of the DUNE source files, or you compile one or more of the DUNE source files and link them with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. dune-localfunctions-2.5.1/README.md000066400000000000000000000017001313314431100167420ustar00rootroot00000000000000DUNE-library ============ DUNE, the Distributed and Unified Numerics Environment is a modular toolbox for solving partial differential equations with grid-based methods. The main intention is to create slim interfaces allowing an efficient use of legacy and/or new libraries. Using C++ techniques DUNE allows to use very different implementation of the same concept (i.e. grid, solver, ...) under a common interface with a very low overhead. DUNE was designed with flexibility in mind. It supports easy discretization using methods, like Finite Elements, Finite Volume and also Finite Differences. Dune-localfunctions ------------------- This module provides interfaces and implementations for local finite element ansatz spaces, i.e., shape functions, associated interpolation functionals, and relation to grid entities. More information ---------------- Check dune-common for more details concerning dependencies, known bugs, license and installation. dune-localfunctions-2.5.1/config.h.cmake000066400000000000000000000026051313314431100201650ustar00rootroot00000000000000/* begin dune-localfunctions put the definitions for config.h specific to your project here. Everything above will be overwritten */ /* begin private */ /* Name of package */ #define PACKAGE "@DUNE_MOD_NAME@" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "@DUNE_MAINTAINER@" /* Define to the full name of this package. */ #define PACKAGE_NAME "@DUNE_MOD_NAME@" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "@DUNE_MOD_NAME@ @DUNE_MOD_VERSION@" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "@DUNE_MOD_NAME@" /* Define to the home page for this package. */ #define PACKAGE_URL "@DUNE_MOD_URL@" /* Define to the version of this package. */ #define PACKAGE_VERSION "@DUNE_MOD_VERSION@" /* end private */ /* Define to the version of dune-localfunctions */ #define DUNE_LOCALFUNCTIONS_VERSION "${DUNE_LOCALFUNCTIONS_VERSION}" /* Define to the major version of dune-localfunctions */ #define DUNE_LOCALFUNCTIONS_VERSION_MAJOR ${DUNE_LOCALFUNCTIONS_VERSION_MAJOR} /* Define to the minor version of dune-localfunctions */ #define DUNE_LOCALFUNCTIONS_VERSION_MINOR ${DUNE_LOCALFUNCTIONS_VERSION_MINOR} /* Define to the revision of dune-localfunctions */ #define DUNE_LOCALFUNCTIONS_VERSION_REVISION ${DUNE_LOCALFUNCTIONS_VERSION_REVISION} /* end dune-localfunctions */ dune-localfunctions-2.5.1/doc/000077500000000000000000000000001313314431100162325ustar00rootroot00000000000000dune-localfunctions-2.5.1/doc/CMakeLists.txt000066400000000000000000000003401313314431100207670ustar00rootroot00000000000000add_subdirectory(doxygen) dune_add_latex_document(dune-localfunctions-manual.tex) create_doc_install(${CMAKE_CURRENT_BINARY_DIR}/dune-localfunctions-manual.pdf ${CMAKE_INSTALL_DOCDIR} dune-localfunctions-manual_safepdf) dune-localfunctions-2.5.1/doc/doxygen/000077500000000000000000000000001313314431100177075ustar00rootroot00000000000000dune-localfunctions-2.5.1/doc/doxygen/CMakeLists.txt000066400000000000000000000001121313314431100224410ustar00rootroot00000000000000# shortcut for creating the Doxyfile.in and Doxyfile add_doxygen_target() dune-localfunctions-2.5.1/doc/doxygen/Doxylocal000066400000000000000000000002661313314431100215740ustar00rootroot00000000000000# Where to search and which files to use INPUT += @srcdir@/mainpage.txt \ @srcdir@/modules.txt \ @top_srcdir@/dune/ dune-localfunctions-2.5.1/doc/doxygen/mainpage.txt000066400000000000000000000006461313314431100222370ustar00rootroot00000000000000/** \mainpage dune-localfunctions Automatic Documentation \section intro Introduction Welcome to the %Dune documentation pages. This documentation has been generated using Doxygen, a free source code documentation system for documenting C/C++ code. \section mods Modules The best way to start is from the page \subpage modules which gives you access to the documentation by category. */ /** \page modules Modules */ dune-localfunctions-2.5.1/doc/doxygen/modules.txt000066400000000000000000000014341313314431100221220ustar00rootroot00000000000000/** * \defgroup LocalFunctions LocalFunctions */ /** * \defgroup BrezziDouglasMarini Brezzi-Douglas-Marini elements * \ingroup LocalFunctions */ /** * \defgroup DualMortar Dual Mortar basis elements * \ingroup LocalFunctions */ /** * \defgroup Lagrange Lagrange elements * \ingroup LocalFunctions */ /** * \defgroup Mimetic Mimetic elements * \ingroup LocalFunctions */ /** * \defgroup Monomial Monomial elements * \ingroup LocalFunctions */ /** * \defgroup Orthonormal Orthonormal elements * \ingroup LocalFunctions */ /** * \defgroup RannacherTurek Rannacher-Turek elements * \ingroup LocalFunctions */ /** * \defgroup RaviartThomas Raviart-Thomas elements * \ingroup LocalFunctions */ /** * \defgroup Whitney Whitney elements * \ingroup LocalFunctions */ dune-localfunctions-2.5.1/doc/dune-localfunctions-manual.tex000066400000000000000000001633021313314431100242100ustar00rootroot00000000000000\documentclass[a4paper,11pt]{article} \usepackage{multicol} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{xspace} \usepackage[body={148mm,240mm,nohead}]{geometry} \usepackage[ansinew]{inputenc} \usepackage{listings} \usepackage{tikz} \usepackage{hyperref} \lstset{language=C++, basicstyle=\ttfamily, stringstyle=\ttfamily, commentstyle=\it, extendedchars=true, breaklines=true } \usepgflibrary{arrows} \newcommand{\dune}{\textsc{Dune}\xspace} \newcommand{\modulename}[1]{\texttt{#1}\xspace} \DeclareMathOperator\sgn{sgn} \title{The dune-localfunctions module} \author{The \dune Team} \date{\today} \begin{document} \maketitle \begin{abstract} This document describes the \modulename{dune-localfunctions} module. The module provides a C++ interface for shape functions needed in finite element methods. A growing list of implementations of this interface is included. \modulename{dune-localfunctions} is part of the Distributed and Unified Numerics Environment (\dune) which is available from the site \url{http://www.dune-project.org/}. \end{abstract} \begin{multicols}{2} {\small\tableofcontents} \end{multicols} \section{Introduction} A feature common to all implementations of finite element methods are the shape functions. In the easier cases, these are polynomial functions defined on a reference element and associated to some face of the reference element. The more complicated non-affine finite elements generalize this by defining the shape functions directly on an element in the grid. Implementations of shape functions are contained in all finite element codes, but in most cases their implementation is so intertwined with the rest of the code as to make their reuse in other situations impossible. For the easier shape functions this may not matter much, as they are fairly easy to implement. Still, errors can occur and bugs in shape function implementations can be difficult to detect and track down. More exotic shape function implementations can get fairly involved and require meticulous care to be done right. For these reasons it is very desirable to provide shape functions in a separate, reusable library. This is what the \modulename{dune-localfunctions} module tries to do. Following the UNIX philosophy of having each program doing only one thing, but doing that thing well, the \modulename{dune-localfunctions} module provides only local and global finite elements. There are two sides to this. \begin{enumerate} \item \modulename{dune-localfunction} prescribes an {\em interface} to shape functions. This interface should be general enough to encompass the needs of virtually all implementors of finite element codes. \item The module contains {\em implementations} of this interface. The set of implementations contains common elements like the Lagrange elements and exotic ones as well. We aim to collect contributions from outside sources and, in time, to be able to provide a shape function library that is virtually complete. \end{enumerate} \subsection{Static vs.\ Dynamic Interfaces} From a textbook C++ perspective, an interface to finite element shape functions can be described naturally using dynamical polymorphism. An abstract base class would describe all methods expected from a shape function implementation, and actual implementations would derive from the base class. Users of shape functions, such as finite element assemblers, would receive shape function implementations through pointers to the abstract base class. However, the run-time overhead of virtual function calls is considered prohibitive by some users. We measured a slowdown of around 7\% when assembling a Laplace stiffness matrix on a two-dimensional structured grid. This can be relevant, for example, in an explicit time-stepping method where a large percentage of the overall time is spent assembling matrices. We have therefore opted for a different way. In \modulename{dune-localfunctions}, the implementation classes are {\em not} organized in a hierarchy. Adherence to a certain interface is enforced only implicitly, by a test suite. Finite element assemblers have to have the C++ type of the shape function implementation as a template parameter, and can then call the object's methods directly. The static interface is described in Section~\ref{sec:static_interface}. Of course such a scheme makes it impossible to select shape function sets at run-time. For example, $p$-adaptive methods, and methods on grids with more than a single element type are precluded. Therefore, \modulename{dune-localfunctions} offers a second way to access its shape functions. There is a set of {\em wrapper classes}, which are organized in a hierarchy using dynamical polymorphism. These wrapper classes are statically parametrized with a static implementation class and forward the function calls to this implementation. Details of this {\em dynamic interface} are given in Section~\ref{sec:dynamic_interface}. \subsection{Dependencies on other Modules} When designing the \modulename{dune-localfunctions} module we have deliberately tried to keep dependencies on other \dune modules to a minimum. Ideally, people should be able to use the shape functions from \dune without having to use anything else from \dune. The only exception here are \modulename{dune-common} and \modulename{dune-geometry} which most \dune modules depend on. \section{\texorpdfstring{The \lstinline!LocalFiniteElement! Interface}{The LocalFiniteElement Interface}} \label{sec:static_interface} The interface of a \lstinline!LocalFiniteElement! is designed to provide the user with all the functionality needed for the implementation of finite element methods. The functionality consists of three subtasks. These are handled by separate classes which can be obtained from the \lstinline!LocalFiniteElement! class. \begin{enumerate} \item The assembly of the local stiffness matrices usually requires the evaluation of the shape functions and/or their derivatives of a certain order $k$ on the reference element. These features are collected in a \lstinline!LocalBasis! class. \item For the correct distribution of the local matrices to the global stiffness matrix one needs to associate the individual shape functions to subentities (i.e., vertices, faces, elements,\dots) of the reference element. This information is provided by a \lstinline!LocalCoefficients! class. An \lstinline!IndexSet! class can then be used to obtain global indices for each shape function. \item Finally one needs to interpolate given functions by the shape functions. This functionality is provided by the \lstinline!LocalInterpolation! class. \end{enumerate} Motivated by these points the interface of a \lstinline!LocalFiniteElement! is given by: \begin{lstlisting} class LocalFiniteElementVirtualInterface { // export traits typedef LocalFiniteElementTraits Traits; // access to the local basis implementation const Traits::LocalBasisType& localBasis() const; // access to the local coefficient implementation const Traits::LocalCoefficientsType& localCoefficients() const; // access to the local interpolation implementation const Traits::LocalInterpolationType& localInterpolation() const; // geometry type the local basis lives on GeometryType type() const; }; \end{lstlisting} The \lstinline!LocalFiniteElementTraits! class is a simple traits helper struct that can be used for the export of the class traits. Each local finite element has to provide an implementation of the three classes that are described in the next sections. \subsection{\texorpdfstring{The \lstinline!LocalBasis! Classes}{The LocalBasis Classes}} The \lstinline!LocalBasis! class represents the set of shape functions: \begin{lstlisting} class LocalBasisInterface { // export type traits for shape function signature typedef LocalBasisTraits Traits; //number of shape functions unsigned int size () const; // evaluate all shape functions at a given position inline void evaluateFunction(const typename Traits::DomainType& in, std::vector& out) const; // evaluate Jacobian of all shape functions at a given position inline void evaluateJacobian(const typename Traits::DomainType& in, std::vector& out) const; // evaluate general derivative of k-th order of all shape functions template inline void evaluate (const typename std::array& directions, const typename Traits::DomainType& in, std::vector& out) const; // polynomial order of the shape functions unsigned int order () const; }; \end{lstlisting} The \texttt{LocalBasisTraits} class is a traits helper class which holds information on how the signature of the shape functions is represented in C++ types. A description of the template parameter above can be found in the doxygen documentation of the traits class. \subsection{\texorpdfstring{The \lstinline!LocalCoefficients! Classes}{The LocalCoefficients Classes}} To describe the position of the degrees of freedom (shape functions) of a \texttt{Local\-Finite\-Element} it is assumed that each degree of freedom can be attached to a subentity of the underlying reference element. For every degree of freedom we thus have \begin{enumerate} \item the local number of the associated subentity \texttt{s}, \item the codimension of the subentity \texttt{c}, \item the index in the set of all shape functions associated to this subentity \texttt{t}. \end{enumerate} These informations are stored in the \lstinline!LocalKey! class, which allows access to the entries by the methods \lstinline!subEntity()!, \lstinline!codim()!, and \lstinline!index()!. For the correct local numbering of the subentities see the documentation of the \lstinline!ReferenceElements! at \url{http://dune-project.org}. The \lstinline!LocalCoefficient! class now associates the indices of the shape function with their corresponding \lstinline!LocalKey!s. \begin{lstlisting} class LocalCoefficientsInterface { // number of coefficients std::size_t size () const; // get i-th index const LocalKey& localKey (std::size_t i) const; }; \end{lstlisting} \subsection{\texorpdfstring{The \lstinline!LocalInterpolation! Classes}{The LocalInterpolation Classes}} \begin{lstlisting} class LocalInterpolationVirtualInterface { // export local basis traits LocalBasisInterface::Traits Traits; // local interpolation of a function template void interpolate (const F& f, std::vector& out) const; }; \end{lstlisting} The \lstinline!LocalInterpolation! class provides a method to interpolate a given function and that returns a coefficient vector for the shape functions. The function class to interpolate must provide a method \lstinline!evaluate(const Traits::DomainType& x, Traits::RangeType& y)!, which is used to evaluate the function on the reference element of the corresponding geometry type. \section{The Dynamic Interface} \label{sec:dynamic_interface} In some situations one doesn't know at compile time which shape function set is needed. This happens for example when grids with several element types are involved or $p$-adaptive methods are used. For this case \modulename{dune-localfunctions} provides a way to select shape functions at run-time. As already described above the implementations of \lstinline!LocalFiniteElement!s are not organized in a hierarchy. Thus, to use dynamic polymorphism we first need a virtual interface and to avoid copying the code we also need a way to re-arrange the existing shape function implementations in a hierarchy. This re-arrangement is done with the help of virtual wrapper classes which take a static implementation as template parameter and forward the dynamic function calls to that implementation. \subsection{The Virtual Interface} From Section \ref{sec:static_interface} we know that in \modulename{dune-localfunctions} a \lstinline!LocalFiniteElement! consists of a \lstinline!LocalBasis!, \lstinline!LocalCoefficients!, and \lstinline!LocalInterpolation! class. So if we want to design a virtual interface for a \lstinline!LocalFiniteElement! we first need to define abstract base classes for these three classes. \paragraph{\lstinline!LocalBasisVirtualInterface!} The \lstinline!LocalBasisVirtualInterface! is organized in a recursive hierarchy of the form \begin{lstlisting} template class LocalBasisVirtualInterface : public virtual LocalBasisVirtualInterface > { typedef LocalBasisVirtualInterface > Base; public: typedef T Traits; using Base::size; using Base::order; using Base::evaluateFunction; using Base::evaluateJacobian; virtual void evaluate ( const typename std::template array& directions, const typename Traits::DomainType& in, std::vector& out) const = 0; }; \end{lstlisting} The \lstinline!LowerOrderLocalBasisTraits! defines a \lstinline!LocalBasisTraits! class (see \ref{sec:static_interface}) with \lstinline!diffOrder! reduced by one (the \lstinline!diffOrder! of a \lstinline!LocalBasis! specifies the maximal order of implemented partial derivatives). This hierarchy is needed because each \lstinline!LocalBasis! implementation is assumed to have a template method \lstinline!evaluate(std::array directions,...)! where \lstinline!k! denotes the total order of mixed partial derivatives to be computed. In the dynamic case this method has to be replaced by non-template methods \lstinline!evaluate(std::array directions,...)! and the hierarchy just makes sure that there will be a corresponding method for all $0 \leq $\lstinline!fixedOrder! $\leq$ \lstinline!diffOrder!. Finally a template specialization for the case \lstinline{diffOrder = 0} provides all pure virtual methods that belong to a \lstinline{LocalBasis}. In the online class documentation of \modulename{dune-localfunctions} you will find another interface class called \lstinline{LocalBasisVirtualInterfaceBase}: The virtual interface additionally provides a non-virtual template method \lstinline{evaluate} which internally calls the non-template \lstinline!evaluate! method. For name resolution reasons this method can thus not be defined in the same class, so there is a second base class, the \lstinline{LocalBasisVirtualInterfaceBase}, which lies between two \lstinline!diffOrder! - levels and that contains this additional method. Note that in applications you should always use the standard \lstinline!LocalBasisVirtualInterface! class. \paragraph{\lstinline!LocalCoefficientsVirtualInterface!} The \lstinline!LocalCoefficientsVirtualInterface! is just the straightforward base class containing the pure virtual methods: \begin{lstlisting} class LocalCoefficientsVirtualInterface { public: virtual ~LocalCoefficientsVirtualInterface() {} //! number of coefficients virtual std::size_t size () const = 0; //! get i'th index const virtual LocalKey& localKey (std::size_t i) const = 0; }; \end{lstlisting} \paragraph{\lstinline!LocalInterpolationVirtualInterface!} For the \lstinline!LocalInterpolationVirtualInterface! we need a similar construction as for the \lstinline!LocalBasisVirtualInterface!. Again we have a template method in the static \lstinline!LocalInterpolation! interface, namely \lstinline!interpolate ()!, which has to be replaced by a non-template method in the dynamic interface. Since we also want to define some non-virtual template methods \lstinline!interpolate! in the interface we again need another abstract base class because of name resolution. \begin{lstlisting} template class LocalInterpolationVirtualInterfaceBase { public: //! type of virtual function to interpolate typedef Dune::VirtualFunction FunctionType; //! type of the coefficient vector in the interpolate method typedef typename RangeType::field_type CoefficientType; virtual ~LocalInterpolationVirtualInterfaceBase() {} virtual void interpolate (const FunctionType& f, std::vector& out) const = 0; }; \end{lstlisting} Now the \lstinline!LocalInterpolationVirtualInterface! derives from this class and additionally contains non-virtual template versions of the \lstinline!interpolate! method which wrap the template parameter \lstinline!FunctionType! into a \lstinline!VirtualFunction! and then call the virtual base method. You can get a proper \lstinline!type! for functions to use with \lstinline!LocalInterpolation! by using\\\lstinline!LocalFiniteElementFunctionBase::type! which is the \lstinline!VirtualFunction! interface class if \lstinline!FE! implements the virtual interface and the \lstinline!Function! base class otherwise. Due to the \lstinline!LocalBasisVirtualInterface! structure the \lstinline!LocalFiniteElementVirtualInterface! is also organized in a hierarchy differing in the order of implemented derivatives. \begin{lstlisting} template class LocalFiniteElementVirtualInterface : public virtual LocalFiniteElementVirtualInterface::Traits > { typedef LocalFiniteElementVirtualInterface::Traits > BaseInterface; public: typedef LocalFiniteElementTraits< LocalBasisVirtualInterface, LocalCoefficientsVirtualInterface, LocalInterpolationVirtualInterface< typename T::DomainType, typename T::RangeType> > Traits; virtual const typename Traits::LocalBasisType& localBasis () const = 0; using BaseInterface::localCoefficients; using BaseInterface::localInterpolation; using BaseInterface::type; virtual LocalFiniteElementVirtualInterface* clone() const = 0; }; \end{lstlisting} While all other member functions are forwarded to the uppermost base class (a template specialization for the case \lstinline!diffOrder=0!) the \lstinline!localBasis()! method has to be provided by every class in the hierarchy since the \lstinline!LocalBasisType! depends on the \lstinline!diffOrder!. The ``virtual copy constructor'' \lstinline!clone! is needed whenever you want to copy a \lstinline!LocalFiniteElement! which derives from the virtual interface and thus the declared type is not equal to the real type. \subsection {The Virtual Wrappers} As already described above in \modulename{dune-localfunctions} the shape functions are not organized in a hierarchy and so since we want to use dynamic polymorphism we would need other shape functions that derive from the virtual interface. Now instead of implementing all the \lstinline!LocalFiniteElement!s a second time we use virtual wrapper class that are statically parametrized by a \lstinline!LocalFiniteElement! (resp. \lstinline!LocalBasis!, etc.) and that derive from the virtual interface. The wrapper classes implement the virtual functions by forwarding them to the static functions. The classes look all very similar and so we only state the \lstinline!LocalCoefficientsVirtualImp!---the wrapper for the \lstinline!LocalCoefficient! class: \begin{lstlisting} template class LocalCoefficientsVirtualImp : public LocalCoefficientsVirtualInterface { template friend class LocalFiniteElementVirtualImp; protected: // constructor taking an implementation of the // Dune::LocalCoefficientsVirtualInterface LocalCoefficientsVirtualImp( const Imp &imp ) : impl_(imp) {} public: std::size_t size () const { return impl_.size(); } const LocalKey& localKey (std::size_t i) const { return impl_.localKey(i); } protected: const Imp& impl_; }; \end{lstlisting} Of course the \lstinline!LocalBasisVirtualImpl! classes must again be organized in a hierarchy differing in the \lstinline!diffOrder! and each class forwards the \lstinline!evaluate! method to the template function of the static implementation: \\ \lstinline!impl_.template evaluate(directions, in, out)! or in the case \lstinline!diffOrder=0! to the \lstinline!evaluateFunction! method. Finally the wrapper class for the \lstinline!LocalFiniteElement! is given by \begin{lstlisting} template class LocalFiniteElementVirtualImp : public virtual LocalFiniteElementVirtualInterface { typedef typename Imp::Traits::LocalBasisType::Traits T; typedef LocalFiniteElementVirtualInterface Interface; public: typedef typename Interface::Traits Traits; LocalFiniteElementVirtualImp( const Imp &imp ) : impl_(LocalFiniteElementCloneFactory::clone(imp)), localBasisImp_(impl_->localBasis()), localCoefficientsImp_(impl_->localCoefficients()), localInterpolationImp_(impl_->localInterpolation()) {} // Default constructor. // Assumes that the implementation class is default constructible LocalFiniteElementVirtualImp() : impl_(LocalFiniteElementCloneFactory::create()), localBasisImp_(impl_->localBasis()), localCoefficientsImp_(impl_->localCoefficients()), localInterpolationImp_(impl_->localInterpolation()) {} // Copy contructor needed for deep copy LocalFiniteElementVirtualImp(const LocalFiniteElementVirtualImp& other) : impl_(LocalFiniteElementCloneFactory::clone(*other.impl_)), localBasisImp_(impl_->localBasis()), localCoefficientsImp_(impl_->localCoefficients()), localInterpolationImp_(impl_->localInterpolation()) {} ~LocalFiniteElementVirtualImp() { delete impl_; } const typename Traits::LocalBasisType& localBasis () const { return localBasisImp_; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return localCoefficientsImp_; } const typename Traits::LocalInterpolationType& localInterpolation () const { return localInterpolationImp_; } const GeometryType type () const { return impl_->type(); } virtual LocalFiniteElementVirtualImp* clone() const { return new LocalFiniteElementVirtualImp(*this); } protected: const Imp* impl_; const LocalBasisVirtualImp localBasisImp_; const LocalCoefficientsVirtualImp< typename Imp::Traits::LocalCoefficientsType> localCoefficientsImp_; const LocalInterpolationVirtualImp localInterpolationImp_; }; \end{lstlisting} The \lstinline!LocalFiniteElementCloneFactory! class uses the \lstinline!clone! method if the implementation derives from the virtual interface and otherwise uses the copy constructor. An example on how the dynamic shape functions are used in applications can be found in the \lstinline!PQkLocalFiniteElementCache! class which is a factory for Lagrangian shape functions of different order and type. \section{Global-valued Finite Elements} So far this document has talked about finite elements on reference elements. However, the finite element is usually needed on an element of a grid. To evaluate a function represented by a finite element basis on a particular grid element $T$ with geometry $\mu$ we can use the following formula: \begin{equation} u(x)=\sum_{i=0}^{N_T-1}c_iP_{T,i}\varphi_i(\mu^{-1}(x)) \qquad\forall x\in T \end{equation} The basis function $\varphi$ on the reference element is provided by the local basis which was described previously. The global basis takes this local basis and applies an operator $P_{T,i}$ to the values it returns. This operator is dependent on the grid element $T$ and the number of the basis function $i$. The global basis thus provides values of the global basis functions \begin{equation} \Phi_i(\hat x)=P_{T,i}\varphi_i(\hat x) \end{equation} For the transformation $P$ the following information about grid element is important: \begin{enumerate} \item The {\em geometry} $\mu$ of a grid element, which handles the transformation of coordinates from the reference element to the grid element. But {\em values} of the base functions and in particular their derivatives need to be transformed as well in general -- the correct transformation depends on the family of the finite element, the coordinate transformation $\mu$ and the number of the base function $i$. \item The {\em vertex ordering} $\tau$ of a grid element, which says how the grid elements vertices are globally numbered in comparison to the numbering in the reference element. This is needed to match multiple dofs on a common sub-entity between two grid elements. Another use is to choose a consistent tangential orientation of edges for edge elements. \item The {\em normal orientation} of faces of a grid element. This is useful for instance for Raviart-Thomas elements: their dofs orientation points from one of the neighbouring elements into the other. This information can generally not be extracted from the vertex ordering and geometry information alone. \end{enumerate} This section explicitly does not deal with the following issues: \begin{itemize} \item Different geometry types for different grid elements. This will lead to different number of basis functions and must already be dealt with in the local finite element. \item $p$-adaptivity. Again, this will lead to different number of basis functions and must already be dealt with in the local finite element. \end{itemize} \subsection{Geometry} The geometry information must be provided by a class basically modelling the interface of {\tt GenericGeometry::BasicGeometry} -- that includes implementations of {\tt Geometry}. The precise requirements are as follows: \begin{lstlisting}[escapechar=\$] struct Geometry { // type information typedef $\em implementation-defined$ ctype; // local dimension static const std::size_t mydimension = $\em implementation-defined$; // global dimension static const std::size_t coorddimension = $\em implementation-defined$; // some vector type with mydimension components of type ctype typedef $\em implementation-defined$ LocalCoordinate; // some vector type with coorddimension components of type ctype typedef $\em implementation-defined$ GlobalCoordinate; // some matrix type with coorddimension x mydimension // components of type ctype typedef $\em implementation-defined$ JacobianInverseTransposed; // some matrix type with mydimension x coorddimension // components of type ctype typedef $\em implementation-defined$ JacobianTransposed; // general properties of the geometry GeometryType type() const; bool affine() const; // access to the coordinates of the corners std::size_t corners() const; GlobalCoordinate corner(std::size_t) const; // local to global and inverse mapping GlobalCoordinate global(const LocalCoordinate&) const; LocalCoordinate local(const GlobalCoordinate&) const; // access to Jacobian of the mapping const JacobianTransposed& jacobianTransposed(const LocalCoordinate&) const; const JacobianInverseTransposed& jacobianInverseTransposed(const LocalCoordinate&) const; // other information GlobalCoordinate center() const; ctype integrationElement(const LocalCoordinate&) const; ctype volume() const; GlobalCoordinate normal(std::size_t face, const LocalCoordinate&) const; }; \end{lstlisting} For the exact meaning of these members look in the doxygen documentation for {\tt Geometry} or {\tt GenericGeometry::BasicGeometry}. The coordinate types ({\tt ctype}, {\tt mydimension}, {\tt coorddimension}, {\tt LocalCoordinate}, and {\tt GlobalCoordinate}) of a {\tt Geometry} object provided when creating an instance of a finite element should coincide with the coordinate types of that finite element's basis class. \subsubsection{Gradient Transformation} The transformation of a scalar function from the reference element to a grid element using the geometry $\mu$ is trivial: \begin{equation} \hat f(\hat x) = f(\mu(\hat x)) \end{equation} The transformation of the gradient of such a function is a little bit more complicated. First we will need to employ the Jacobian, which we define for a function $u$ as: \begin{equation} J_u(x)=\begin{pmatrix} \partial_0u_0|_x & \ldots & \partial_{n-1}u_0|_x \\ \vdots & \ddots & \vdots \\ \partial_0u_{m-1}|_x & \ldots & \partial_{n-1}u_{m-1}|_x \end{pmatrix} \end{equation} This definition of the Jacobian lets us write a linear vector-valued function $u$ in terms of its Jacobian $J_u$ as $u(x) = J_u \cdot x$. For a scalar valued function $f$ the gradient is the transpose of the Jacobian: \begin{equation} \nabla f|_x = \begin{pmatrix} \partial_0f|_x \\ \vdots \\ \partial_{n-1}f|_x \end{pmatrix} = J_f^T(x) \end{equation} To do the actual transformation we employ the chain rule \begin{equation} \hat J_{\hat f}({\hat x}) = J_f(\mu(\hat x))\cdot \hat J_\mu(\hat x) \end{equation} After transposing, left-multiplying by $\hat J_\mu^{-T}(\hat x)$ and replacing the transposed Jacobians by gradient where applicable, we obtain \begin{equation} \nabla f|_{\mu(\hat x)} = \hat J_\mu^{-T}(\hat x) \cdot \hat\nabla\hat f|_{\hat x} \end{equation} \subsubsection{Piola Transformation for Raviart-Thomas Elements} Raviart-Thomas elements are finite elements that ensure continuity of the normal component across grid elements. They do allow for jumps in the tangential components, however. For these elements, the degrees-of-freedom (dofs) are usually associated with the face (sub-entity of codimension 1) on which the normal component is non-zero. \begin{tikzpicture}[scale=2] \begin{scope} \draw[clip] (0,0) -- (1,0) -- (0,1) --cycle; \foreach \y in {.1,.3,...,.9} \foreach \x in {1,.7,.5,.35,.25,.175,.125,.0875,.0625} \draw[<-] (1-\x,\y*\x) -- +(\x/4,-\y*\x/4); \end{scope} \path (0,0) node[below left] {$x^0$} (1,0) node[below right] {$x^1$} (0,1) node[above left] {$x^2$}; \draw[->,thick] (.1,.5) -- (-.1,.5) node[left] {$\hat\varphi^1$}; \fill (0,.5) circle (.02); \end{tikzpicture} These elements have the following property: \begin{equation} \varphi^i(x)\cdot n^j=\delta_{ij}\quad\forall x\in\text{face $j$} \end{equation} Here $n^j$ is the outer normal unit vector to face $j$ and $\delta_{ij}$ is the Kronecker delta. Naturally, transforming the basis should preserve that property. This is achieved by the Piola-transformation: \begin{equation} \varphi^i(\mu(\hat x)) = \frac{\hat J_\mu(\hat x)}{|\hat J_\mu(\hat x)|} \hat\varphi^i(\hat x) \end{equation} \subsubsection{Edge Elements} Edge elements are used in finite element electro-magnetics. In the lowest order, their dofs are associated with edges, i.e.\ sub-entities of dimension 1. They can be expressed in terms of first order node-based Lagrange finite elements $L^i$ as follows: \begin{equation} N^i = \ell^i(L^{i_0} \nabla L^{i_1} - L^{i_1} \nabla L^{i_0}) \end{equation} Here $i_0$ and $i_1$ are the indices of the nodes at the endpoints of edge $i$ and $\ell^i$ is the length of edge $i$. \begin{tikzpicture}[scale=2] \begin{scope} \draw[clip] (0,0) -- (1,0) -- (0,1) --cycle; \foreach \x in {.1,.3,...,1.5} \foreach \a in {2.5,17.5,32.5} \draw[->] (1,0) +(180-\a:\x) arc(180-\a:170-\a:\x); \end{scope} \path (0,0) node[below left] {$x^0$} (1,0) node[below right] {$x^1$} (0,1) node[above left] {$x^2$}; \draw[->,thick] (0,.4) -- (0,.6); \fill (0,.5) circle (.02) node[left] {$\hat N^1$}; \end{tikzpicture} Edge elements have a similar property as Raviart-Thomas elements: the tangential component is 1 on the associated edge and 0 on all other edges: \begin{equation} N^i(x)\cdot t^j=\delta_{ij}\quad\forall x\in\text{edge $j$} \end{equation} For the transformation we make the ansatz \begin{equation} N^i(\mu(\hat x)) = \alpha^iA\hat N^i(\hat x) \end{equation} with the scalars $\alpha^i$ and a matrix $A$. We express $N^i$ and $\hat N^i$ in terms of the corresponding P1 bases \begin{equation} \ell^i\{L^{i_0}(\mu(\hat x)) \cdot \nabla L^{i_1}|_{\mu(\hat x)} - L^{i_1}(\mu(\hat x)) \cdot \nabla L^{i_0}|_{\mu(\hat x)}\} = \alpha^iA\hat\ell^i\{ \hat L^{i_0}(\hat x) \cdot \hat\nabla\hat L^{i_1}|_{\hat x} - \hat L^{i_1}(\hat x) \cdot \hat\nabla\hat L^{i_0}|_{\hat x}\} \end{equation} By replacing the global P1 bases by their transformations \begin{align} L^i(\mu(\hat x)) &= \hat L^i(\hat x) \\ \nabla L^i|_{\mu(\hat x)} &= \hat J_\mu^{-T}(\hat x) \hat\nabla\hat L^i|_{\hat x} \end{align} we obtain \begin{multline} \ell^i\hat J_\mu^{-T}(\hat x)\{ \hat L^{i_0}(\hat x) \cdot \hat\nabla\hat L^{i_1}|_{\hat x} - \hat L^{i_1}(\hat x) \cdot \hat\nabla\hat L^{i_0}|_{\hat x}\} \\ = \alpha^iA\hat\ell^i\{ \hat L^{i_0}(\hat x) \cdot \hat\nabla\hat L^{i_1}|_{\hat x} - \hat L^{i_1}(\hat x) \cdot \hat\nabla\hat L^{i_0}|_{\hat x}\} \end{multline} The expression inside the curly braces on both sides is the same. We identify \begin{align} A &= \hat J_\mu^{-T}(\hat x) \\ \alpha^i &= \ell^i/\hat\ell^i \end{align} The full transformation then looks like this: \begin{equation} N^i(\mu(\hat x)) = \frac{\ell^i}{\hat\ell^i} \hat J_\mu^{-T}(\hat x) \cdot \hat N^i(\hat x) \end{equation} Note that this transformation only works for the base functions, not for superpositions of them. Each base function $N^i$ has a different transformation because the base multiplier $\alpha^i$ depends on the number of the base function. \subsubsection{Conclusions} From the examples above we can conclude that the following information is needed from a {\tt Geometry} class. It is quite possible that the list below is incomplete since the examples above may have missed some piece of information that may be needed in general. \begin{itemize} \item The inverse transposed of the Jacobian $\hat J_\mu^{-T}(\hat x)$. \item The Jacobian itself $\hat J_\mu(\hat x)$. \item The determinant of the Jacobian $|\hat J_\mu(\hat x)|$. \item The lengths of the edges of the grid element $\ell^i$. \item The lengths of the edges of the reference element $\hat\ell^i$. \end{itemize} When local coordinates $\hat x$ are provided the local-to-global map $\mu(\hat x)$ and its inverse $\mu^{-1}(x)$ as well as the corner coordinates $x^i$ themselves are never needed. This makes the required information independent of a shift in the global coordinates and opens an optimisation possibility for regular grids. \subsection{Vertex Ordering} The vertex ordering information is based completely on the global numbering of the vertices of a grid element. To obtain it, we collect the global IDs of the vertices in a vector indexed by the indices of the vertices within the reference element: \begin{lstlisting} void collectVertexIds(const Element& e, const GlobalIdSet& idSet, std::vector& ids) { ids.resize(e.geometry().corners()); for(int i = 0; i < ids.size(); ++ids) ids[i] = idSet.subId(e, i, Element::dimension); } \end{lstlisting} In the next step the {\em ordering reduction} operation is applied: the smallest id in the array is replaced by the number 0, the second-smallest is replaced by the number 1 etc. \begin{lstlisting} template void reduceOrder(const InIterator& inBegin, const InIterator& inEnd, OutIterator outIt) { static const std::less< typename std::iterator_traits::value_type > less; for(InIterator inIt = inBegin; inIt != inEnd; ++inIt, ++outIt) *outIt = std::count(inBegin, inEnd, std::bind2nd(less, *inIt)); } \end{lstlisting} To obtain an actual vector of reduced indices one can use the following code: \begin{lstlisting} std::vector ids; collectVertexIds(elem, globalIdSet, ids); std::vector reduced_indices(ids.size()); reduceOrder(ids.begin(), ids.end(), reduced_indices.begin()); \end{lstlisting} As an example, lets assume we have a quadrilateral or a tetrahedron with the global ids of the vertices being 14 for vertex 0, 27 for vertex 1, 3 for vertex 2 and 800 for vertex 3. After ordering reduction the reduced vector will contain 1, 2, 0 and 3 in that order. When determining the vertex ordering for a sub-entity, the reduced indices corresponding to the vertices sub-entity are extracted into a smaller vector and the reduction is applied again, at least conceptually. In reality, the reduction is mostly only necessary because the type of the global ids may be a complicated non-integral struct, and we want to keep the vertex ordering information as lean as possible. The actual information is always contained in the relative ordering of the indices/ids, and the reduction preserves that. The ordering information can always be obtained from the global ids of the vertices. However, for some grids, such as ALUGrid, using the global ids is quiet expensive. On the other hand, ALUGrid already stores a twist of the faces, which can be easily extracted and contains the same information as the vertex ordering, just encoded in a different way. Though this does not provide vertex ordering information for the whole element, this information is seldom needed. To accommodate all sides, we define an interface class {\tt VertexOrderingInterface}. Implementations of this interface can be used to provide vertex ordering information. Grids that store the vertex ordering internally for certain sub-entities can provide an optimised implementation. These implementations may omit vertex ordering information for sub-entities where such information is not readily available; they should throw {\tt NotImplemented} if such information is requested anyway. Note that the information is still required to be consistent for those sub-entities where information is available: Consider a tetrahedron and pick two triangular faces $A$ and $B$ with a common edge. If someone requests vertex ordering information for one of the faces and reduces that information to the edge, the result must be the same no matter whether face $A$ or $B$ was used or whether the ordering was requested directly for the edge itself. The interface for the class is as follows: \begin{lstlisting} struct VertexOrderingInterface { // dimension of the entity this applies to static const std::size_t dimension; // geometry type of the entity this applies to const GeometryType type() const; // iterate over some sub-entity's vertex indices // must be a RandomAccess iterator, value_type may be constant class iterator; // get begin iterator for the vertex indices of some sub-entity iterator begin(std::size_t codim, std::size_t subEntity) const; // get end iterator for the vertex indices of some sub-entity iterator begin(std::size_t codim, std::size_t subEntity) const; // get reduced vertex ordering for the specified sub-entity void getReduced(std::size_t codim, std::size_t subEntity, std::vector& order) const; }; \end{lstlisting} Information about the dimension and the geometry type is included because it determines the limits for the parameters (via the {\tt ReferenceElements}). The {\tt getReduced()} method shall resize the vector passed in the {\tt order} parameter to the suitable size. \subsection{Matching Multiple Dofs on a Common Sub-Entity} Some finite elements have more than one dof on a given sub-entity of an element, and assign a position inside the sub-entity to that dof (i.e.\ Pk $k\geq4$, Qk $k\geq3$). For conforming schemes the ordering of the dofs on a sub-entity shared by two or more elements must match such that the dofs on the same position can be identified. A similar situation arises with edge elements of order $1.5$: For simplices they have three base functions on a face but only two of them are independent. A finite element implementation must make sure to pick the same two base functions for the face in neighbouring elements so their dofs can be identified. Both issues can be addressed using the information provided by the ordering of the global ids of the vertices. \subsection{Flipping of Base Function Values} Some finite element families, most notably Raviart-Thomas and edge elements, assign an orientation to (some of) their dofs. That is, the value of the dof $a^i$ is interpolated from a function $u$ as the functions value at the dofs position $x^i$ projected onto some unit vector $e^i$: \begin{equation} a^i = u(x^i)\cdot e^i \end{equation} The direction of that unit vector is the orientation of the dof. For Raviart-Thomas $e^i$ is the unit vector normal to the face (codimension 1 sub-entity), for edge elements $e^i$ is the unit vector tangential to the edge (dimension 1 sub-entity) on which the dof is located. To be continuous over element borders, elements connected to a common sub-entity must agree upon a common global orientation for that sub-entity. If their local orientation differs from the global orientation, the {\tt Basis} must multiply the value of the corresponding basis function by $-1$. The tricky part is the to determine the global orientation for the common sub-entity correctly. \subsubsection{Tangential Orientation for Lines} Lines have two vertices which can be used to choose the orientation of the line: the orientation vector points from the vertex with the lower index/id to the vertex with the higher index/id. That is the geometric interpretation, we actually don't want to compare coordinates, but preferably just integers. To obtain the local orientation, of an edge in an element, collect the indices of the edges vertices, and here we mean {\em indices inside the reference element} of the element: \begin{lstlisting} unsigned local_orientation[2]; local_orientation[0] = refelem.subEntity(edge_index, dim-1, 0, dim); local_orientation[1] = refelem.subEntity(edge_index, dim-1, 1, dim); \end{lstlisting} For the global orientation we do basically the same. However, this time we use the vertex ordering information derived from the global ids of the vertices of the element instead of vertex indices inside the reference element: \begin{lstlisting} unsigned global_orientation[2]; global_orientation[0] = vertex_order[local_orientation[0]]; global_orientation[1] = vertex_order[local_orientation[1]]; \end{lstlisting} The ordering of the index values determines the local and global orientation: \begin{lstlisting} if((local_orientation[0] < local_orientation[1]) == (global_orientation[0] < global_orientation[1])) { // local and global orientation are identical; nothing to do } else { // local and global orientation differ; flip base function value } \end{lstlisting} \subsubsection{Normal Orientation for Codimension 1 Sub-Entities} Normal orientation for sub-entities of codimension 1 is important for Raviart-Thomas elements. Normal orientation is more tricky and cannot be done using the ordering of the indices/id of the corners alone. Some additional information is needed, such as the sign of the determinant of the Jacobian of the geometry map $\sgn(\det(\hat J_\mu))$. This is however not enough for lower dimensional grids in a higher dimensional world, since then the Jacobian is no longer quadratic and has no determinant. The reason why the information about the vertex ids is not enough is roughly that to construct the normal orientation there is alway some kind of rotation involved. In 2D the codimension 1 sub-entities are edges. We can obtain a normal orientation by rotating the tangential orientation by 90°. To get a consistent result however, this rotation must be done in the global coordinate system for the global orientation and in the respective local coordinate systems for the local orientations. Locally on the element we have only the local coordinate system available, however. If the geometric transformation $\mu$ involves mirroring, then the sense of the rotation will be different for the local and the global coordinate system. The sign of the Jacobian's determinant can tell us whether there is mirroring involved or not. In 3D the construction of the orientation differs: for triangles we walk through the indices/ids in ascending order and determine the direction of the normal vector by the right-hand rule: \\\hspace*{\fill} \begin{tikzpicture} \draw (0,0) node[below left] {0} -- (1,0) node[below right] {1} -- (0,1) node[above left] {2} --cycle; \coordinate (c) at (.29289,.29289); \draw (c) circle (.2); \fill (c) circle (.05); \end{tikzpicture} \begin{tikzpicture} \draw (0,0) node[below left] {0} -- (1,0) node[below right] {2} -- (0,1) node[above left] {1} --cycle; \coordinate (c) at (.29289,.29289); \draw (c) circle (.2); \draw (c) +(45:.2) -- +(45:-.2) +(-45:.2) -- +(-45:-.2); \end{tikzpicture} \hspace*{\fill}\\ Similar for quadrilaterals, although if their indices/ids are acyclic we just have to pick and orientation (here we chose to ignore the highest index/id and determine the orientation from the remaining indices/ids as for triangles): \\\hspace*{\fill} \begin{tikzpicture} \draw (0,0) node[below left] {0} -- (1,0) node[below right] {1} -- (1,1) node[above right] {3} -- (0,1) node[above left] {2} --cycle; \coordinate (c) at (.5,.5); \draw (c) circle (.2); \fill (c) circle (.05); \end{tikzpicture} \begin{tikzpicture} \draw (0,0) node[below left] {0} -- (1,0) node[below right] {2} -- (1,1) node[above right] {3} -- (0,1) node[above left] {1} --cycle; \coordinate (c) at (.5,.5); \draw (c) circle (.2); \draw (c) +(45:.2) -- +(45:-.2) +(-45:.2) -- +(-45:-.2); \end{tikzpicture} \begin{tikzpicture} \draw (0,0) node[below left] {0} -- (1,0) node[below right] {1} -- (1,1) node[above right] {2} -- (0,1) node[above left] {3} --cycle; \coordinate (c) at (.5,.5); \draw (c) circle (.2); \fill (c) circle (.05); \end{tikzpicture} \begin{tikzpicture} \draw (0,0) node[below left] {0} -- (1,0) node[below right] {3} -- (1,1) node[above right] {2} -- (0,1) node[above left] {1} --cycle; \coordinate (c) at (.5,.5); \draw (c) circle (.2); \draw (c) +(45:.2) -- +(45:-.2) +(-45:.2) -- +(-45:-.2); \end{tikzpicture} \hspace*{\fill} This is all rather tedious and in fact there is a much simpler way, which will even work in the case of lower-dimensional grids in a higher-dimensional world. Sub-entities of codimension 1 are always situated between two Elements. Choosing a normal orientation for the sub-entity means to choose a vector that points from one element into the other. The global orientation can thus be chosen by comparing the ids of the elements: it points outward in the element with the lower id and inward in the element with the higher id. The face orientation should be passed as a bool vector: \begin{lstlisting} typedef std::vector FaceOrientation; \end{lstlisting} The vector is indexed by the index of the face in the reference element. A value of {\tt true} means the global orientation of the face is outward, {\tt false} means it is inward. \subsection{API} The API for global-valued finite elements consists of five interface classes ({\tt Basis\-Inter\-face}, {\tt InterpolationInterface}, {\tt Coefficients\-Interface}, {\tt FiniteElementInterface}, and {\tt Finite\-Element\-Factory\-Interface}) and two traits classes ({\tt BasisTraits} and {\tt Finite\-Element\-Traits}). In contrast to the local interface which prefixes all its names with ``{\tt Local}'' we do not use any prefix here. ``{\tt Local}'' is already taken, ``{\tt Global}'' would suggest that this interface is completely in global coordinates, ``{\tt GlobalValue}'' is too clumsy and adds too much to the lengths of names. \subsubsection{Finite Element Interface} \begin{lstlisting}[escapechar=\$] struct FiniteElementInterface { // types of component objects struct Traits { typedef $\em implementation-defined$ Basis; typedef $\em implementation-defined$ Coefficients; typedef $\em implementation-defined$ Interpolation; }; // constructor arguments are implementation specific FiniteElementInterface(...); // ... except for the copy constructor FiniteElementInterface(const FiniteElementInterface&); // extract component objects const typename Traits::Basis& basis() const; const typename Traits::Coefficients& coefficients() const; const typename Traits::Interpolation& interpolation() const; GeometryType type() const; }; \end{lstlisting} The member class {\tt Traits} may be a member typedef instead. Constructor signatures and existence is implementation-defined, except for the copy constructor, which must be present and publicly accessible. Construction is generally done by a factory class. To keep copy-construction efficient it is recommended that instances of this class are light proxy objects. The reason to mandate copy-construction is as follows: Up to now with local finite elements \modulename{dune-pdelab} used the class {\tt FiniteElementMap} as a kind of finite element factory. If the finite element was required in different variants for a given grid (i.e.\ because normal continuity was required for Raviar-Thomas elements), the {\tt FiniteElementMap} would store all the variants internally and return a reference to the correct variant upon request. Since global-valued finite elements depend on the geometry of the grid element, this trick is no longer useful, especially if you plan to modify the finite element object by ``binding'' it to the geometry. The problem is that more than one finite element for different grid elements may be required at the same time (think iterating over the intersections). If the {\tt FiniteElementMap} returns the same variant for both grid elements the user code will first bind the finite element to the inside element and later to the outside element, since both of his finite element references point to the same object. Thus when he tries to access the inside finite element, he will in reality access the outside element. \subsubsection{Finite Element Factory Interface} \begin{lstlisting}[escapechar=\$] struct FiniteElementFactoryInterface { // may also be an inline class typedef $\em implementation-defined$ FiniteElement; // construction is implementation-defined FiniteElementFactoryInterface(...); // finite element object creation // arguments are implementation defined const FiniteElement make(...); }; \end{lstlisting} The method to create a finite element object is {\tt make()}. The created object is returned by value ({\tt const FiniteElement}). The factory implementation may choose to return by reference instead ({\tt const FiniteElement\&}). Because temporaries may be bound to const references in C++, this way code using the factory can always bind the returned value to a const reference and avoid copy construction if that is not necessary: \begin{lstlisting} const Factory::FiniteElement& fe = factory.make(); \end{lstlisting} In any case, the returned value or reference must be valid for as long as the factory object exists. Since each finite element family will need different information to create a finite element object tailored to a particular grid element, the actual argument of the {\tt male()} are implementation-defined. Earlier in this section we have seen different types of information which may be needed to create a tailored finite element: geometry, vertex ordering and face orientation. If they are needed for a given finite element implementation, that finite element should require necessary items in the order given above and in the encoding given earlier. If neither geometry nor vertex ordering is required, but the geometry type is, that should be given in place of geometry and vertex ordering directly. Any extra information should be given after these arguments. The possible signatures for make thus are: \begin{lstlisting} make(const Geometry&, const VertexOrder&, const FaceOrientation&, ...); make(const Geometry&, const VertexOrder&, ...); make(const Geometry&, const FaceOrientation&, ...); make(const Geometry&, ...); make(const VertexOrder&, const FaceOrientation&, ...); make(const VertexOrder&, ...); make(const GeometryType&, const FaceOrientation&, ...); make(const GeometryType&, ...); make(const FaceOrientation&, ...); make(...); \end{lstlisting} Implementation must document what kind of arguments are required for {\tt make()}. The constructor signature is implementation-defined. It is recommended that the factory caches as much information as possible. For instance, for regular hypercube grids the Jacobian of the geometry does not change and is the only thing needed to transform the derivatives. For this case the constructor should take a sample geometry and precompute the transformation. Whether the regular and the general case are distinguished by different constructor arguments to the same factory class, or whether there is one factory class for the regular and one for the general case is left to the implementor of the factory. \subsubsection{Basis Interface} \begin{lstlisting}[escapechar=\$] struct BasisInterface { struct Traits { // domain properties (local and global) typedef $\em implementation-defined$ DomainField; static const std::size_t dimDomainLocal = $\em implementation-defined$; static const std::size_t dimDomainGlobal = $\em implementation-defined$; typedef $\em implementation-defined$ DomainLocal; typedef $\em implementation-defined$ DomainGlobal; // range properties (global range only) typedef $\em implementation-defined$ RangeField; static const std::size_t dimRange = $\em implementation-defined$; typedef $\em implementation-defined$ Range; // jacobian properties (dimRange x dimDomainGlobal Matrix with // components of type RangeField) typedef $\em implementation-defined$ Jacobian; // maximum number of partial derivatives supported static const std::size_t diffOrder = $\em implementation-defined$; }; // Number of shape functions std::size_t size () const; // Polynomial order of the shape functions for quadrature std::size_t order () const; // Evaluate all shape functions at given position void evaluateFunction ( const typename Traits::DomainLocal& in, std::vector& out) const; // Evaluate jacobian of all shape functions at given position // required for Traits::diffOrder >= 1 void evaluateJacobian ( const typename Traits::DomainLocal& in, std::vector& out) const; // Evaluate derivatives of all shape functions at given position // required for Traits::diffOrder >= 2 void evaluate ( const std::array& directions, const typename Traits::DomainLocal& in, std::vector& out) const; }; \end{lstlisting} The basis interface closely follows the local basis interface with some notable exceptions. First there are the types in the traits class. Since coordinates are still given in the reference elements coordinate system but derivatives are done with respect to global coordinates, a distinction must be made between local and global domain. The other change is that the member types of the traits class no longer have a suffix ``{\tt Type}'' since it is quite clear from the camel-case naming convention that they are types. Second the method for general derivatives {\tt evaluate()} is no longer a template method and its argument {\tt directions} has different semantics. In the local basis interface, {\tt directions} was a list of directions in which to take derivatives, i.e.\ {\tt directions=\{0, 1, 0, 2\}} for the derivative $\partial_0\partial_1\partial_0\partial_2$. This is inconvenient since it requires {\tt directions} to be a list of variable length, making the length a template parameter, and because the order implied in the above derivative does not really exist, it can just as well be written as $\partial_0^2\partial_1\partial_2$. So in the global-value interface {\tt directions} lists the exponents in the last expression: {\tt direction=\{2, 1, 1\}}. This way the length of {\tt directions} will always be {\tt Traits::dimDomainGlobal} and {\tt evaluate()} no longer needs to be a template. \subsubsection{Interpolation Interface} \begin{lstlisting} struct InterpolationInterface { // Export basis traits typedef BasisInterface::Traits Traits; // determine coefficients interpolating a given function template void interpolate (const F& f, std::vector& out) const; }; \end{lstlisting} The interface for global-value interpolation objects also has little modifications compared to local interpolation objects. Main addition is the member type {\tt Traits} which is the same as in the corresponding basis class. This is to document the parameter types that {\tt interpolate()} will use to evaluate the function {\tt f}. For the member method {\tt evaluate()} the requirements for the function object {\tt f} change slightly: it is still required to support the expression {\tt f.evaluate(x, y)}, and {\tt x} in that expression is still a local coordinate (though the type is named a little bit different: {\tt const Traits::DomainLocal\&}. The difference is that the returned value {\tt y} is now in global coordinates and of the type {\tt Traits::Range}. \subsection{Coefficients Interface} \begin{lstlisting} struct CoefficientsInterface { // number of coefficients std::size_t size() const; // get i'th index const LocalKey& localKey(std::size_t i) const; }; \end{lstlisting} The interface for the coefficients class is exactly the same as for the local coefficients. If the global-valued finite elements is implemented in term of a local finite element it will often be possible to simply reuse the coefficients class of the local finite element. If there is some dof-matching required for common sub-entities of neighbouring elements however, and this dof-matching can be done entirely by reordering the dofs on the sub-entity, then the coefficients class is the place to do it. \section{Appendix: List of Available Elements} % bibtex bibliography %\bibliographystyle{plain} %\bibliography{istl.bib} \end{document} dune-localfunctions-2.5.1/dune-localfunctions.pc.in000066400000000000000000000005371313314431100223770ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ CXX=@CXX@ CC=@CC@ DEPENDENCIES=@REQUIRES@ Name: @PACKAGE_NAME@ Version: @VERSION@ Description: Dune (Distributed and Unified Numerics Environment) local functions module URL: http://dune-project.org/ Requires: ${DEPENDENCIES} Libs: -L${libdir} Cflags: -I${includedir} dune-localfunctions-2.5.1/dune.module000066400000000000000000000002201313314431100176210ustar00rootroot00000000000000Module: dune-localfunctions Version: 2.5.1 Maintainer: dune-devel@lists.dune-project.org Depends: dune-geometry (>= 2.5.0) Whitespace-Hook: Yes dune-localfunctions-2.5.1/dune/000077500000000000000000000000001313314431100164205ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/CMakeLists.txt000066400000000000000000000000411313314431100211530ustar00rootroot00000000000000add_subdirectory(localfunctions) dune-localfunctions-2.5.1/dune/localfunctions/000077500000000000000000000000001313314431100214435ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/CMakeLists.txt000066400000000000000000000016501313314431100242050ustar00rootroot00000000000000add_subdirectory(brezzidouglasmarini) add_subdirectory(common) add_subdirectory(dualmortarbasis) add_subdirectory(hierarchical) add_subdirectory(lagrange) add_subdirectory(meta) add_subdirectory(mimetic) add_subdirectory(monomial) add_subdirectory(orthonormal) add_subdirectory(rannacherturek) add_subdirectory(raviartthomas) add_subdirectory(refined) add_subdirectory(test) add_subdirectory(utility) add_subdirectory(whitney) install(FILES dualmortarbasis.hh lagrange.hh mimetic.hh monomial.hh orthonormal.hh rannacherturek.hh raviartthomas.hh refined.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions) # Install some test headers, because they might be useful for tests in # other modules. # We do this here as test will not be considered for make install. install(FILES test/geometries.hh test/test-fe.hh test/test-localfe.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/test) dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/000077500000000000000000000000001313314431100255275ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/CMakeLists.txt000066400000000000000000000007571313314431100303000ustar00rootroot00000000000000add_subdirectory(brezzidouglasmarini1cube2d) add_subdirectory(brezzidouglasmarini1cube3d) add_subdirectory(brezzidouglasmarini2cube2d) add_subdirectory(brezzidouglasmarini1simplex2d) add_subdirectory(brezzidouglasmarini2simplex2d) install(FILES brezzidouglasmarini1cube2d.hh brezzidouglasmarini1cube3d.hh brezzidouglasmarini2cube2d.hh brezzidouglasmarini1simplex2d.hh brezzidouglasmarini2simplex2d.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini) dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d.hh000066400000000000000000000043461313314431100333110ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_QUBE2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_QUBE2D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "brezzidouglasmarini1cube2d/brezzidouglasmarini1cube2dlocalbasis.hh" #include "brezzidouglasmarini1cube2d/brezzidouglasmarini1cube2dlocalcoefficients.hh" #include "brezzidouglasmarini1cube2d/brezzidouglasmarini1cube2dlocalinterpolation.hh" namespace Dune { /** * \brief First order Brezzi-Douglas-Marini shape functions on quadrilaterals. * * \ingroup BrezziDouglasMarini * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class BDM1Cube2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< BDM1Cube2DLocalBasis, BDM1Cube2DLocalCoefficients, BDM1Cube2DLocalInterpolation > > Traits; //! \brief Standard constructor BDM1Cube2DLocalFiniteElement () { gt.makeQuadrilateral(); } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ BDM1Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeQuadrilateral(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: BDM1Cube2DLocalBasis basis; BDM1Cube2DLocalCoefficients coefficients; BDM1Cube2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_QUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d/000077500000000000000000000000001313314431100327615ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004111313314431100354360ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2dinstall(FILES brezzidouglasmarini1cube2dlocalbasis.hh brezzidouglasmarini1cube2dlocalcoefficients.hh brezzidouglasmarini1cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d) brezzidouglasmarini1cube2dlocalbasis.hh000066400000000000000000000133311313314431100425130ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALBASIS_HH #include #include #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief First order Brezzi-Douglas-Marini shape functions on the reference quadrilateral. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class BDM1Cube2DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor BDM1Cube2DLocalBasis () { for (size_t i=0; i<4; i++) sign_[i] = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ BDM1Cube2DLocalBasis (std::bitset<4> s) { for (size_t i=0; i<4; i++) sign_[i] = s[i] ? -1.0 : 1.0; } //! \brief number of shape functions unsigned int size () const { return 8; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(8); out[0][0] = sign_[0]*(in[0] - 1.0); out[0][1] = 0.0; out[1][0] = 6.0*in[0]*in[1] - 3.0*in[0]-6*in[1] + 3.0; out[1][1] = -3.0*in[1]*in[1] + 3.0*in[1]; out[2][0] = sign_[1]*(in[0]); out[2][1] = 0.0; out[3][0] = -6.0*in[0]*in[1] + 3.0*in[0]; out[3][1] = 3.0*in[1]*in[1] - 3.0*in[1]; out[4][0] = 0.0; out[4][1] = sign_[2]*(in[1] - 1.0); out[5][0] = 3.0*in[0]*in[0] - 3.0*in[0]; out[5][1] = -6.0*in[0]*in[1] + 6.0*in[0] + 3.0*in[1] - 3.0; out[6][0] = 0.0; out[6][1] = sign_[3]*(in[1]); out[7][0] = -3.0*in[0]*in[0] + 3.0*in[0]; out[7][1] = 6.0*in[0]*in[1] - 3.0*in[1]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const typename Traits::DomainType& in, std::vector& out) const { out.resize(8); out[0][0][0] = sign_[0]; out[0][0][1] = 0.0; out[0][1][0] = 0.0; out[0][1][1] = 0.0; out[1][0][0] = 6.0*in[1] - 3.0; out[1][0][1] = 6.0*in[0] - 6.0; out[1][1][0] = 0.0; out[1][1][1] = -6.0*in[1] + 3.0; out[2][0][0] = sign_[1]; out[2][0][1] = 0.0; out[2][1][0] = 0.0; out[2][1][1] = 0.0; out[3][0][0] = -6.0*in[1] + 3.0; out[3][0][1] = -6.0*in[0]; out[3][1][0] = 0.0; out[3][1][1] = 6.0*in[1] - 3.0; out[4][0][0] = 0.0; out[4][0][1] = 0.0; out[4][1][0] = 0.0; out[4][1][1] = sign_[2]; out[5][0][0] = 6.0*in[0] - 3.0; out[5][0][1] = 0.0; out[5][1][0] = -6.0*in[1] + 6.0; out[5][1][1] = -6.0*in[0] + 3.0; out[6][0][0] = 0.0; out[6][0][1] = 0.0; out[6][1][0] = 0.0; out[6][1][1] = sign_[3]; out[7][0][0] = -6.0*in[0] + 3.0; out[7][0][1] = 0.0; out[7][1][0] = 6.0*in[1]; out[7][1][1] = 6.0*in[0] - 3.0; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0][0] = sign_[0]; out[0][1] = 0.0; out[1][0] = 6.0*in[1] - 3.0; out[1][1] = 0.0; out[2][0] = sign_[1]; out[2][1] = 0.0; out[3][0] = -6.0*in[1] + 3.0; out[3][1] = 0.0; out[4][0] = 0.0; out[4][1] = 0.0; out[5][0] = 6.0*in[0] - 3.0; out[5][1] = -6.0*in[1] + 6.0; out[6][0] = 0.0; out[6][1] = 0.0; out[7][0] = -6.0*in[0] + 3.0; out[7][1] = 6.0*in[1]; break; case 1: out[0][0] = 0.0; out[0][1] = 0.0; out[1][0] = 6.0*in[0] - 6.0; out[1][1] = -6.0*in[1] + 3.0; out[2][0] = 0.0; out[2][1] = 0.0; out[3][0] = -6.0*in[0]; out[3][1] = 6.0*in[1] - 3.0; out[4][0] = 0.0; out[4][1] = sign_[2]; out[5][0] = 0.0; out[5][1] = -6.0*in[0] + 3.0; out[6][0] = 0.0; out[6][1] = sign_[3]; out[7][0] = 0.0; out[7][1] = 6.0*in[0] - 3.0; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 2; } private: std::array sign_; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALBASIS_HH brezzidouglasmarini1cube2dlocalcoefficients.hh000066400000000000000000000022141313314431100440510ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \ingroup LocalLayoutImplementation * \brief Layout map for Brezzi-Douglas-Marini-1 elements on quadrilaterals * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class BDM1Cube2DLocalCoefficients { public: //! \brief Standard constructor BDM1Cube2DLocalCoefficients () : li(8) { for (std::size_t i = 0; i < 4; ++i) { li[2*i] = LocalKey(i,1,0); li[2*i + 1] = LocalKey(i,1,1); } } //! \brief number of coefficients std::size_t size () const { return 8; } //! \brief get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALCOEFFICIENTS_HH brezzidouglasmarini1cube2dlocalinterpolation.hh000066400000000000000000000067631313314431100443140ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \ingroup LocalInterpolationImplementation * \brief First order Brezzi-Douglas-Marini shape functions on the reference quadrilateral. * * \tparam LB corresponding LocalBasis giving traits * * \nosubgrouping */ template class BDM1Cube2DLocalInterpolation { public: //! \brief Standard constructor BDM1Cube2DLocalInterpolation () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ BDM1Cube2DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } if (s & 8) { sign3 = -1.0; } n0[0] = -1.0; n0[1] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n3[0] = 0.0; n3[1] = 1.0; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; //typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(8); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const QuadratureRule& rule = QuadratureRules::rule(GeometryType(GeometryType::cube,1), qOrder); for (typename QuadratureRule::const_iterator it = rule.begin(); it != rule.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0; out[1] += (y[0]*n0[0] + y[1]*n0[1])*(2.0*qPos - 1.0)*it->weight(); localPos[0] = 1.0; localPos[1] = qPos; f.evaluate(localPos, y); out[2] += (y[0]*n1[0] + y[1]*n1[1])*it->weight()*sign1; out[3] += (y[0]*n1[0] + y[1]*n1[1])*(1.0 - 2.0*qPos)*it->weight(); localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[4] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2; out[5] += (y[0]*n2[0] + y[1]*n2[1])*(1.0 - 2.0*qPos)*it->weight(); localPos[0] = qPos; localPos[1] = 1.0; f.evaluate(localPos, y); out[6] += (y[0]*n3[0] + y[1]*n3[1])*it->weight()*sign3; out[7] += (y[0]*n3[0] + y[1]*n3[1])*(2.0*qPos - 1.0)*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2, sign3; typename LB::Traits::DomainType n0, n1, n2, n3; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d.hh000066400000000000000000000043621313314431100333100ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_QUBE3D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_QUBE3D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "brezzidouglasmarini1cube3d/brezzidouglasmarini1cube3dlocalbasis.hh" #include "brezzidouglasmarini1cube3d/brezzidouglasmarini1cube3dlocalcoefficients.hh" #include "brezzidouglasmarini1cube3d/brezzidouglasmarini1cube3dlocalinterpolation.hh" namespace Dune { /** * \brief First order Brezzi-Douglas-Marini shape functions on hexahedron. * * \ingroup BrezziDouglasMarini * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class BDM1Cube3DLocalFiniteElement { public: typedef LocalFiniteElementTraits< BDM1Cube3DLocalBasis, BDM1Cube3DLocalCoefficients, BDM1Cube3DLocalInterpolation > > Traits; //! \brief Standard constructor BDM1Cube3DLocalFiniteElement() { gt.makeHexahedron(); } /** * \brief Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ BDM1Cube3DLocalFiniteElement(int s) : basis(s), interpolation(s) { gt.makeHexahedron(); } const typename Traits::LocalBasisType& localBasis() const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients() const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation() const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type() const { return gt; } private: BDM1Cube3DLocalBasis basis; BDM1Cube3DLocalCoefficients coefficients; BDM1Cube3DLocalInterpolation > interpolation; GeometryType gt; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_QUBE3D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d/000077500000000000000000000000001313314431100327625ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004111313314431100354370ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3dinstall(FILES brezzidouglasmarini1cube3dlocalbasis.hh brezzidouglasmarini1cube3dlocalcoefficients.hh brezzidouglasmarini1cube3dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d) brezzidouglasmarini1cube3dlocalbasis.hh000066400000000000000000000350101313314431100425130ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALBASIS_HH #include #include #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief First order Brezzi-Douglas-Marini shape functions on the reference * hexahedron. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class BDM1Cube3DLocalBasis { public: typedef LocalBasisTraits, R,3,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor BDM1Cube3DLocalBasis() { for (size_t i=0; i<6; i++) sign_[i] = 1.0; } /** * \brief Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ BDM1Cube3DLocalBasis(std::bitset<6> s) { for (size_t i=0; i<6; i++) sign_[i] = s[i] ? -1.0 : 1.0; } //! \brief number of shape functions unsigned int size() const { return 18; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); out[0][0] = sign_[0] * (in[0] - 1.0); out[0][1] = 0.0; out[0][2] = 0.0; out[1][0] = sign_[1] * in[0]; out[1][1] = 0.0; out[1][2] = 0.0; out[2][0] = 0.0; out[2][1] = sign_[2] * (in[1] - 1.0); out[2][2] = 0.0; out[3][0] = 0.0; out[3][1] = sign_[3] * in[1]; out[3][2] = 0.0; out[4][0] = 0.0; out[4][1] = 0.0; out[4][2] = sign_[4] * (in[2] - 1.0); out[5][0] = 0.0; out[5][1] = 0.0; out[5][2] = sign_[5] * in[2]; out[6][0] = 6.0 * in[0] * in[1] - 3 * in[0]-6 * in[1] + 3.0; out[6][1] = -3.0 * in[1] * in[1] + 3 * in[1]; out[6][2] = 0.0; out[7][0] = -6.0 * in[0] * in[1] + 3 * in[0]; out[7][1] = 3.0 * in[1] * in[1] - 3 * in[1]; out[7][2] = 0.0; out[8][0] = 3.0 * in[0] * in[0] - 3 * in[0]; out[8][1] = -6.0 * in[0] * in[1] + 3 * in[1]+6 * in[0]-3.0; out[8][2] = 0.0; out[9][0] = -3.0 * in[0] * in[0] + 3 * in[0]; out[9][1] = 6.0 * in[0] * in[1] - 3 * in[1]; out[9][2] = 0.0; out[10][0] = -3.0 * in[0] * in[0] + 3 * in[0]; out[10][1] = 0.0; out[10][2] = 6.0 * in[0] * in[2]-6 * in[0]-3 * in[2] + 3.0; out[11][0] = 3.0 * in[0] * in[0]-3 * in[0]; out[11][1] = 0.0; out[11][2] = -6.0 * in[0] * in[2] + 3 * in[2]; out[12][0] = -6.0 * in[0] * in[2]+6 * in[2] + 3 * in[0]-3.0; out[12][1] = 0.0; out[12][2] = 3.0 * in[2] * in[2]-3 * in[2]; out[13][0] = -3 * in[0]+6 * in[0] * in[2]; out[13][1] = 0.0; out[13][2] = -3.0 * in[2] * in[2] + 3 * in[2]; out[14][0] = 0.0; out[14][1] = 6.0 * in[1] * in[2]-3 * in[1]-6 * in[2] + 3.0; out[14][2] = -3 * in[2] * in[2] + 3 * in[2]; out[15][0] = 0.0; out[15][1] = -6.0 * in[1] * in[2] + 3 * in[1]; out[15][2] = 3.0 * in[2] * in[2]-3 * in[2]; out[16][0] = 0.0; out[16][1] = 3.0 * in[1] * in[1]-3 * in[1]; out[16][2] = -6.0 * in[1] * in[2] + 3 * in[2]+6 * in[1]-3.0; out[17][0] = 0.0; out[17][1] = -3.0 * in[1] * in[1] + 3 * in[1]; out[17][2] = 6.0 * in[1] * in[2] - 3.0 * in[2]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); out[0][0][0] = sign_[0]; out[0][0][1] = 0; out[0][0][2] = 0; out[0][1][0] = 0; out[0][1][1] = 0; out[0][1][2] = 0; out[0][2][0] = 0; out[0][2][1] = 0; out[0][2][2] = 0; out[1][0][0] = sign_[1]; out[1][0][1] = 0; out[1][0][2] = 0; out[1][1][0] = 0; out[1][1][1] = 0; out[1][1][2] = 0; out[1][2][0] = 0; out[1][2][1] = 0; out[1][2][2] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[2][1][0] = 0; out[2][1][1] = sign_[2]; out[2][1][2] = 0; out[2][2][0] = 0; out[2][2][1] = 0; out[2][2][2] = 0; out[3][0][0] = 0; out[3][0][1] = 0; out[3][0][2] = 0; out[3][1][0] = 0; out[3][1][1] = sign_[3]; out[3][1][2] = 0; out[3][2][0] = 0; out[3][2][1] = 0; out[3][2][2] = 0; out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 0; out[4][1][0] = 0; out[4][1][1] = 0; out[4][1][2] = 0; out[4][2][0] = 0; out[4][2][1] = 0; out[4][2][2] = sign_[4]; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[5][1][0] = 0; out[5][1][1] = 0; out[5][1][2] = 0; out[5][2][0] = 0; out[5][2][1] = 0; out[5][2][2] = sign_[5]; out[6][0][0] = 6*in[1]-3; out[6][0][1] = 6*in[0]-6; out[6][0][2] = 0.0; out[6][1][0] = 0.0; out[6][1][1] =-6*in[1]+3; out[6][1][2] = 0.0; out[6][2][0] = 0.0; out[6][2][1] = 0.0; out[6][2][2] = 0.0; out[7][0][0] = -6*in[1]+3; out[7][0][1] =-6*in[0]; out[7][0][2] = 0.0; out[7][1][0] = 0.0; out[7][1][1] = 6*in[1]-3; out[7][1][2] = 0.0; out[7][2][0] = 0.0; out[7][2][1] = 0.0; out[7][2][2] = 0.0; out[8][0][0] = 6*in[0]-3; out[8][0][1] = 0.0; out[8][0][2] = 0.0; out[8][1][0] =-6*in[1]+6; out[8][1][1] =-6*in[0]+3; out[8][1][2] = 0.0; out[8][2][0] = 0.0; out[8][2][1] = 0.0; out[8][2][2] = 0.0; out[9][0][0] = -6*in[0]+3; out[9][0][1] = 0.0; out[9][0][2] = 0.0; out[9][1][0] = 6*in[1]; out[9][1][1] = 6*in[0]-3; out[9][1][2] = 0.0; out[9][2][0] = 0.0; out[9][2][1] = 0.0; out[9][2][2] = 0.0; out[10][0][0] = -6*in[0]+3; out[10][0][1] = 0.0; out[10][0][2] = 0.0; out[10][1][0] = 0.0; out[10][1][1] = 0.0; out[10][1][2] = 0.0; out[10][2][0] =6*in[2]-6; out[10][2][1] = 0.0; out[10][2][2] =6*in[0]-3; out[11][0][0] =6*in[0]-3; out[11][0][1] = 0.0; out[11][0][2] = 0.0; out[11][1][0] = 0.0; out[11][1][1] = 0.0; out[11][1][2] = 0.0; out[11][2][0] = -6*in[2]; out[11][2][1] = 0.0; out[11][2][2] = -6*in[0]+3; out[12][0][0] = -6*in[2]+3; out[12][0][1] =0.0; out[12][0][2] = -6*in[0]+6; out[12][1][0] = 0.0; out[12][1][1] = 0.0; out[12][1][2] = 0.0; out[12][2][0] = 0.0; out[12][2][1] = 0.0; out[12][2][2] =6*in[2]-3; out[13][0][0] =6*in[2]-3; out[13][0][1] = 0.0; out[13][0][2] = 6*in[0]; out[13][1][0] = 0.0; out[13][1][1] = 0.0; out[13][1][2] = 0.0; out[13][2][0] = 0.0; out[13][2][1] = 0.0; out[13][2][2] =-6*in[2]+3; out[14][0][0] = 0.0; out[14][0][1] = 0.0; out[14][0][2] = 0.0; out[14][1][0] = 0.0; out[14][1][1] = 6*in[2]-3; out[14][1][2] = 6*in[1]-6; out[14][2][0] = 0.0; out[14][2][1] = 0.0; out[14][2][2] =-6*in[2]+3; out[15][0][0] = 0.0; out[15][0][1] = 0.0; out[15][0][2] = 0.0; out[15][1][0] = 0.0; out[15][1][1] =-6*in[2]+3; out[15][1][2] =-6*in[1]; out[15][2][0] = 0.0; out[15][2][1] = 0.0; out[15][2][2] = 6*in[2]-3; out[16][0][0] = 0.0; out[16][0][1] = 0.0; out[16][0][2] = 0.0; out[16][1][0] = 0.0; out[16][1][1] = 6*in[1]-3; out[16][1][2] = 0.0; out[16][2][0] = 0.0; out[16][2][1] =-6*in[2]+6; out[16][2][2] =-6*in[1]+3; out[17][0][0] = 0.0; out[17][0][1] = 0.0; out[17][0][2] = 0.0; out[17][1][0] = 0.0; out[17][1][1] =-6*in[1]+3; out[17][1][2] = 0.0; out[17][2][0] = 0.0; out[17][2][1] = 6*in[2]; out[17][2][2] = 6*in[1]-3; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0][0] = sign_[0]; out[0][1] = 0; out[0][2] = 0; out[1][0] = sign_[1]; out[1][1] = 0; out[1][2] = 0; out[2][0] = 0; out[2][1] = 0; out[2][2] = 0; out[3][0] = 0; out[3][1] = 0; out[3][2] = 0; out[4][0] = 0; out[4][1] = 0; out[4][2] = 0; out[5][0] = 0; out[5][1] = 0; out[5][2] = 0; out[6][0] = 6*in[1]-3; out[6][1] = 0.0; out[6][2] = 0.0; out[7][0] = -6*in[1]+3; out[7][1] = 0.0; out[7][2] = 0.0; out[8][0] = 6*in[0]-3; out[8][1] =-6*in[1]+6; out[8][2] = 0.0; out[9][0] = -6*in[0]+3; out[9][1] = 6*in[1]; out[9][2] = 0.0; out[10][0] = -6*in[0]+3; out[10][1] = 0.0; out[10][2] =6*in[2]-6; out[11][0] =6*in[0]-3; out[11][1] = 0.0; out[11][2] = -6*in[2]; out[12][0] = -6*in[2]+3; out[12][1] = 0.0; out[12][2] = 0.0; out[13][0] =6*in[2]-3; out[13][1] = 0.0; out[13][2] = 0.0; out[14][0] = 0.0; out[14][1] = 0.0; out[14][2] = 0.0; out[15][0] = 0.0; out[15][1] = 0.0; out[15][2] = 0.0; out[16][0] = 0.0; out[16][1] = 0.0; out[16][2] = 0.0; out[17][0] = 0.0; out[17][1] = 0.0; out[17][2] = 0.0; break; case 1: out[0][0] = 0; out[0][1] = 0; out[0][2] = 0; out[1][0] = 0; out[1][1] = 0; out[1][2] = 0; out[2][0] = 0; out[2][1] = sign_[2]; out[2][2] = 0; out[3][0] = 0; out[3][1] = sign_[3]; out[3][2] = 0; out[4][0] = 0; out[4][1] = 0; out[4][2] = 0; out[5][0] = 0; out[5][1] = 0; out[5][2] = 0; out[6][0] = 6*in[0]-6; out[6][1] =-6*in[1]+3; out[6][2] = 0.0; out[7][0] =-6*in[0]; out[7][1] = 6*in[1]-3; out[7][2] = 0.0; out[8][0] = 0.0; out[8][1] =-6*in[0]+3; out[8][2] = 0.0; out[9][0] = 0.0; out[9][1] = 6*in[0]-3; out[9][2] = 0.0; out[10][0] = 0.0; out[10][1] = 0.0; out[10][2] = 0.0; out[11][0] = 0.0; out[11][1] = 0.0; out[11][2] = 0.0; out[12][0] =0.0; out[12][1] = 0.0; out[12][2] = 0.0; out[13][0] = 0.0; out[13][1] = 0.0; out[13][2] = 0.0; out[14][0] = 0.0; out[14][1] = 6*in[2]-3; out[14][2] = 0.0; out[15][0] = 0.0; out[15][1] =-6*in[2]+3; out[15][2] = 0.0; out[16][0] = 0.0; out[16][1] = 6*in[1]-3; out[16][2] =-6*in[2]+6; out[17][0] = 0.0; out[17][1] =-6*in[1]+3; out[17][2] = 6*in[2]; break; case 2: out[0][0] = 0; out[0][1] = 0; out[0][2] = 0; out[1][0] = 0; out[1][1] = 0; out[1][2] = 0; out[2][0] = 0; out[2][1] = 0; out[2][2] = 0; out[3][0] = 0; out[3][1] = 0; out[3][2] = 0; out[4][0] = 0; out[4][1] = 0; out[4][2] = sign_[4]; out[5][0] = 0; out[5][1] = 0; out[5][2] = sign_[5]; out[6][0] = 0.0; out[6][1] = 0.0; out[6][2] = 0.0; out[7][0] = 0.0; out[7][1] = 0.0; out[7][2] = 0.0; out[8][0] = 0.0; out[8][1] = 0.0; out[8][2] = 0.0; out[9][0] = 0.0; out[9][1] = 0.0; out[9][2] = 0.0; out[10][0] = 0.0; out[10][1] = 0.0; out[10][2] =6*in[0]-3; out[11][0] = 0.0; out[11][1] = 0.0; out[11][2] = -6*in[0]+3; out[12][0] = -6*in[0]+6; out[12][1] = 0.0; out[12][2] =6*in[2]-3; out[13][0] = 6*in[0]; out[13][1] = 0.0; out[13][2] =-6*in[2]+3; out[14][0] = 0.0; out[14][1] = 6*in[1]-6; out[14][2] =-6*in[2]+3; out[15][0] = 0.0; out[15][1] =-6*in[1]; out[15][2] = 6*in[2]-3; out[16][0] = 0.0; out[16][1] = 0.0; out[16][2] =-6*in[1]+3; out[17][0] = 0.0; out[17][1] = 0.0; out[17][2] = 6*in[1]-3; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order() const { return 2; } private: std::array sign_; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALBASIS_HH brezzidouglasmarini1cube3dlocalcoefficients.hh000066400000000000000000000022761313314431100440630ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \ingroup LocalLayoutImplementation * \brief Layout map for Brezzi-Douglas-Marini-1 elements on hexahedra * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class BDM1Cube3DLocalCoefficients { public: //! \brief Standard constructor BDM1Cube3DLocalCoefficients() : li(18) { for (std::size_t i = 0; i < 6; ++i) { li[i] = LocalKey(i,1,0); li[i + 6] = LocalKey(i,1,1); li[i + 12] = LocalKey(i,1,2); } } //! \brief number of coefficients std::size_t size() const { return 18; } //! \brief get i'th index const LocalKey& localKey(std::size_t i) const { return li[i]; } private: std::vector li; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALCOEFFICIENTS_HH brezzidouglasmarini1cube3dlocalinterpolation.hh000066400000000000000000000060441313314431100443060ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \brief First order Brezzi-Douglas-Marini shape functions on the reference * hexahedron. * * \tparam LB corresponding LocalBasis giving traits * * \ingroup LocalInterpolationImplementation * \nosubgrouping */ template class BDM1Cube3DLocalInterpolation { public: //! \brief Standard constructor BDM1Cube3DLocalInterpolation() { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; } /** * \brief Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ BDM1Cube3DLocalInterpolation(unsigned int s) { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } if (s & 8) { sign3 = -1.0; } if (s & 16) { sign4 = -1.0; } if (s & 32) { sign5 = -1.0; } n0[0] = -1.0; n0[1] = 0.0; n0[2] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n1[2] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n2[2] = 0.0; n3[0] = 0.0; n3[1] = 1.0; n3[2] = 0.0; n4[0] = 0.0; n4[1] = 0.0; n4[2] = -1.0; n5[0] = 0.0; n5[1] = 0.0; n5[2] = 1.0; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate(const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; //typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; DUNE_THROW( NotImplemented, "Interpolation for BDM1Cube3D finite elements is not implemented." ); out.resize(18); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const QuadratureRule& rule = QuadratureRules::rule(GeometryType(GeometryType::cube,1), qOrder); for (typename QuadratureRule::const_iterator it = rule.begin(); it != rule.end(); ++it) { // TODO: write interpolation } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2, sign3, sign4, sign5; typename LB::Traits::DomainType n0, n1, n2, n3, n4, n5; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_CUBE3D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d.hh000077500000000000000000000044231313314431100340530ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "brezzidouglasmarini1simplex2d/brezzidouglasmarini1simplex2dlocalbasis.hh" #include "brezzidouglasmarini1simplex2d/brezzidouglasmarini1simplex2dlocalcoefficients.hh" #include "brezzidouglasmarini1simplex2d/brezzidouglasmarini1simplex2dlocalinterpolation.hh" namespace Dune { /** * \brief First order Brezzi-Douglas-Marini shape functions on triangles. * * \ingroup BrezziDouglasMarini * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class BDM1Simplex2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< BDM1Simplex2DLocalBasis, BDM1Simplex2DLocalCoefficients, BDM1Simplex2DLocalInterpolation > > Traits; //! \brief Standard constructor BDM1Simplex2DLocalFiniteElement () { gt.makeTriangle(); } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ BDM1Simplex2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeTriangle(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: BDM1Simplex2DLocalBasis basis; BDM1Simplex2DLocalCoefficients coefficients; BDM1Simplex2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d/000077500000000000000000000000001313314431100335245ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004251313314431100362060ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2dinstall(FILES brezzidouglasmarini1simplex2dlocalbasis.hh brezzidouglasmarini1simplex2dlocalcoefficients.hh brezzidouglasmarini1simplex2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d) brezzidouglasmarini1simplex2dlocalbasis.hh000077500000000000000000000115341313314431100440270ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALBASIS_HH #include #include #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief First order Brezzi-Douglas-Marini shape functions on the reference triangle. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class BDM1Simplex2DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor BDM1Simplex2DLocalBasis () { for (size_t i=0; i<3; i++) sign_[i] = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ BDM1Simplex2DLocalBasis (std::bitset<3> s) { for (size_t i=0; i<3; i++) sign_[i] = s[i] ? -1.0 : 1.0; } //! \brief number of shape functions unsigned int size () const { return 6; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(6); out[0][0] = sign_[0]*in[0]; out[0][1] = sign_[0]*(in[1] - 1.0); out[1][0] = sign_[1]*(in[0] - 1.0); out[1][1] = sign_[1]*in[1]; out[2][0] = sign_[2]*in[0]; out[2][1] = sign_[2]*in[1]; out[3][0] = 3.0*in[0]; out[3][1] = 3.0 - 6.0*in[0] - 3.0*in[1]; out[4][0] = -3.0 + 3.0*in[0] + 6.0*in[1]; out[4][1] = -3.0*in[1]; out[5][0] = -3.0*in[0]; out[5][1] = 3.0*in[1]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const typename Traits::DomainType& in, std::vector& out) const { out.resize(6); out[0][0][0] = sign_[0]; out[0][0][1] = 0.0; out[0][1][0] = 0.0; out[0][1][1] = sign_[0]; out[1][0][0] = sign_[1]; out[1][0][1] = 0.0; out[1][1][0] = 0.0; out[1][1][1] = sign_[1]; out[2][0][0] = sign_[2]; out[2][0][1] = 0.0; out[2][1][0] = 0.0; out[2][1][1] = sign_[2]; out[3][0][0] = 3.0; out[3][0][1] = 0.0; out[3][1][0] = -6.0; out[3][1][1] = -3.0; out[4][0][0] = 3.0; out[4][0][1] = 6.0; out[4][1][0] = 0.0; out[4][1][1] = -3.0; out[5][0][0] = -3.0; out[5][0][1] = 0.0; out[5][1][0] = 0.0; out[5][1][1] = 3.0; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0][0] = sign_[0]; out[0][1] = 0.0; out[1][0] = sign_[1]; out[1][1] = 0.0; out[2][0] = sign_[2]; out[2][1] = 0.0; out[3][0] = 3.0; out[3][1] = -6.0; out[4][0] = 3.0; out[4][1] = 0.0; out[5][0] = -3.0; out[5][1] = 0.0; break; case 1: out[0][0] = 0.0; out[0][1] = sign_[0]; out[1][0] = 0.0; out[1][1] = sign_[1]; out[2][0] = 0.0; out[2][1] = sign_[2]; out[3][0] = 0.0; out[3][1] = -3.0; out[4][0] = 6.0; out[4][1] = -3.0; out[5][0] = 0.0; out[5][1] = 3.0; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 1; } private: std::array sign_; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALBASIS_HH brezzidouglasmarini1simplex2dlocalcoefficients.hh000077500000000000000000000022171313314431100453650ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \ingroup LocalLayoutImplementation * \brief Layout map for Brezzi-Douglas-Marini-1 elements on triangles. * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class BDM1Simplex2DLocalCoefficients { public: //! \brief Standard constructor BDM1Simplex2DLocalCoefficients () : li(6) { for (std::size_t i=0; i<3; i++) { li[i] = LocalKey(i,1,0); li[3 + i] = LocalKey(i,1,1); } } //! \brief number of coefficients std::size_t size () const { return 6; } //! \brief get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALCOEFFICIENTS_HH brezzidouglasmarini1simplex2dlocalinterpolation.hh000077500000000000000000000064721313314431100456220ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \ingroup LocalInterpolationImplementation * \brief First order Brezzi-Douglas-Marini shape functions on the reference triangle. * * \tparam LB corresponding LocalBasis giving traits * * \nosubgrouping */ template class BDM1Simplex2DLocalInterpolation { public: //! \brief Standard constructor BDM1Simplex2DLocalInterpolation () { sign0 = sign1 = sign2 = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ BDM1Simplex2DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } n0[0] = 0.0; n0[1] = -1.0; n1[0] = -1.0; n1[1] = 0.0; n2[0] = 1.0/sqrt(2.0); n2[1] = 1.0/sqrt(2.0); c0 = 0.5*n0[0] - 1.0*n0[1]; c1 = -1.0*n1[0] + 0.5*n1[1]; c2 = 0.5*n2[0] + 0.5*n2[1]; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typename F::Traits::RangeType y; out.resize(6); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const Dune::QuadratureRule& rule = Dune::QuadratureRules::rule(Dune::GeometryType(Dune::GeometryType::simplex,1), qOrder); for (typename Dune::QuadratureRule::const_iterator it=rule.begin(); it!=rule.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0/c0; out[3] += (y[0]*n0[0] + y[1]*n0[1])*(2.0*qPos - 1.0)*it->weight()/c0; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[1] += (y[0]*n1[0] + y[1]*n1[1])*it->weight()*sign1/c1; out[4] += (y[0]*n1[0] + y[1]*n1[1])*(1.0 - 2.0*qPos)*it->weight()/c1; localPos[0] = 1.0 - qPos; localPos[1] = qPos; f.evaluate(localPos, y); out[2] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2/c2; out[5] += (y[0]*n2[0] + y[1]*n2[1])*(2.0*qPos - 1.0)*it->weight()/c2; } } private: typename LB::Traits::RangeFieldType sign0,sign1,sign2; typename LB::Traits::DomainType n0,n1,n2; typename LB::Traits::RangeFieldType c0,c1,c2; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d.hh000066400000000000000000000043471313314431100333130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_QUBE2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_QUBE2D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "brezzidouglasmarini2cube2d/brezzidouglasmarini2cube2dlocalbasis.hh" #include "brezzidouglasmarini2cube2d/brezzidouglasmarini2cube2dlocalcoefficients.hh" #include "brezzidouglasmarini2cube2d/brezzidouglasmarini2cube2dlocalinterpolation.hh" namespace Dune { /** * \brief Second order Brezzi-Douglas-Marini shape functions on quadrilaterals. * * \ingroup BrezziDouglasMarini * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class BDM2Cube2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< BDM2Cube2DLocalBasis, BDM2Cube2DLocalCoefficients, BDM2Cube2DLocalInterpolation > > Traits; //! \brief Standard constructor BDM2Cube2DLocalFiniteElement () { gt.makeQuadrilateral(); } /** * \brief Make set number s, where 0 <= s < ?? * * \param s Edge orientation indicator */ BDM2Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeQuadrilateral(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: BDM2Cube2DLocalBasis basis; BDM2Cube2DLocalCoefficients coefficients; BDM2Cube2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_QUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d/000077500000000000000000000000001313314431100327625ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004111313314431100354370ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2dinstall(FILES brezzidouglasmarini2cube2dlocalbasis.hh brezzidouglasmarini2cube2dlocalcoefficients.hh brezzidouglasmarini2cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d) brezzidouglasmarini2cube2dlocalbasis.hh000066400000000000000000000247511313314431100425250ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALBASIS_HH #include #include #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief First order Brezzi-Douglas-Marini shape functions on quadrilaterals. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class BDM2Cube2DLocalBasis { public: typedef LocalBasisTraits, R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor BDM2Cube2DLocalBasis() { for (size_t i=0; i<4; i++) sign_[i] = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ BDM2Cube2DLocalBasis(std::bitset<4> s) { for (size_t i=0; i<4; i++) sign_[i] = s[i] ? -1.0 : 1.0; } //! \brief number of shape functions unsigned int size() const { return 14; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); out[0][0] = sign_[0]*(-2.25 + 5.25*in[0] + 7.5*in[1] - 7.5*in[0]*in[1] - 3.0*in[0]*in[0] - 7.5*in[1]*in[1] + 7.5*in[0]*in[1]*in[1]); out[0][1] = sign_[0]*(-1.25*in[1] + 3.75*in[1]*in[1] - 2.5*in[1]*in[1]*in[1]); out[1][0] = 3.0 - 3.0*in[0]-6.0*in[1] + 6.0*in[0]*in[1]; out[1][1] = 0.0; out[2][0] = sign_[0]*(-3.75 + 3.75*in[0] + 22.5*in[1] - 22.5*in[0]*in[1] - 22.5*in[1]*in[1] + 22.5*in[0]*in[1]*in[1]); out[2][1] = sign_[0]*(-3.75*in[1] + 11.25*in[1]*in[1] - 7.5*in[1]*in[1]*in[1]); out[3][0] = sign_[1]*(-0.75*in[0] - 7.5*in[0]*in[1] + 3.0*in[0]*in[0] + 7.5*in[0]*in[1]*in[1]); out[3][1] = sign_[1]*(-1.25*in[1] + 3.75*in[1]*in[1] - 2.5*in[1]*in[1]*in[1]); out[4][0] = 3.0*in[0] - 6.0*in[0]*in[1]; out[4][1] = 0.0; out[5][0] = sign_[1]*(+3.75*in[0] - 22.5*in[0]*in[1] + 22.5*in[0]*in[1]*in[1]); out[5][1] = sign_[1]*(-3.75*in[1] + 11.25*in[1]*in[1] - 7.5*in[1]*in[1]*in[1]); out[6][0] = sign_[2]*(-1.25*in[0] + 3.75*in[0]*in[0] - 2.5*in[0]*in[0]*in[0]); out[6][1] = sign_[2]*(-2.25 + 7.5*in[0] + 5.25*in[1] - 7.5*in[0]*in[1] - 7.5*in[0]*in[0] - 3.0*in[1]*in[1] + 7.5*in[0]*in[0]*in[1]); out[7][0] = 0.0; out[7][1] = -3.0 + 6.0*in[0] + 3.0*in[1] - 6.0*in[0]*in[1]; out[8][0] = sign_[2]*(-3.75*in[0] + 11.25*in[0]*in[0] - 7.5*in[0]*in[0]*in[0]); out[8][1] = sign_[2]*(-3.75 + 22.5*in[0] + 3.75*in[1] - 22.5*in[0]*in[1] - 22.5*in[0]*in[0] + 22.5*in[0]*in[0]*in[1]); out[9][0] = sign_[3]*(-1.25*in[0] + 3.75*in[0]*in[0] - 2.5*in[0]*in[0]*in[0]); out[9][1] = sign_[3]*(-0.75*in[1] - 7.5*in[0]*in[1] + 3.0*in[1]*in[1] + 7.5*in[0]*in[0]*in[1]); out[10][0] = 0.0; out[10][1] = -3.0*in[1] + 6.0*in[0]*in[1]; out[11][0] = sign_[3]*(-3.75*in[0] + 11.25*in[0]*in[0] - 7.5*in[0]*in[0]*in[0]); out[11][1] = sign_[3]*(3.75*in[1] - 22.5*in[0]*in[1] + 22.5*in[0]*in[0]*in[1]); out[12][0] = 6.0*in[0] - 6.0*in[0]*in[0]; out[12][1] = 0.0; out[13][0] = 0.0; out[13][1] = 6.0*in[1] - 6.0*in[1]*in[1]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); out[0][0][0] = sign_[0]*(5.25 - 7.5*in[1] - 6.0*in[0] + 7.5*in[1]*in[1]); out[0][0][1] = sign_[0]*(7.5 - 7.5*in[0] - 15.0*in[1] + 15.0*in[0]*in[1]); out[0][1][0] = 0.0; out[0][1][1] = sign_[0]*(-1.25 + 7.5*in[1] - 7.5*in[1]*in[1]); out[1][0][0] = -3.0 + 6.0*in[1]; out[1][0][1] = -6.0 + 6.0*in[0]; out[1][1][0] = 0.0; out[1][1][1] = 0.0; out[2][0][0] = sign_[0]*(3.75 - 22.5*in[1] + 22.5*in[1]*in[1]); out[2][0][1] = sign_[0]*(22.5 - 22.5*in[0] - 45.0*in[1] + 45.0*in[0]*in[1]); out[2][1][0] = 0.0; out[2][1][1] = sign_[0]*(-3.75 + 22.5*in[1] - 22.5*in[1]*in[1]); out[3][0][0] = sign_[1]*(-0.75 - 7.5*in[1] + 6.0*in[0] + 7.5*in[1]*in[1]); out[3][0][1] = sign_[1]*(-7.5*in[0] + 15.0*in[0]*in[1]); out[3][1][0] = 0.0; out[3][1][1] = sign_[1]*(-1.25 + 7.5*in[1] - 7.5*in[1]*in[1]); out[4][0][0] = 3.0 - 6.0*in[1]; out[4][0][1] = -6.0*in[0]; out[4][1][0] = 0.0; out[4][1][1] = 0.0; out[5][0][0] = sign_[1]*(3.75 - 22.5*in[1] + 22.5*in[1]*in[1]); out[5][0][1] = sign_[1]*(-22.5*in[0] + 45.0*in[0]*in[1]); out[5][1][0] = 0.0; out[5][1][1] = sign_[1]*(-3.75 + 22.5*in[1] - 22.5*in[1]*in[1]); out[6][0][0] = sign_[2]*(-1.25 + 7.5*in[0] - 7.5*in[0]*in[0]); out[6][0][1] = 0.0; out[6][1][0] = sign_[2]*(7.5 - 7.5*in[1] - 15.0*in[0] + 15.0*in[0]*in[1]); out[6][1][1] = sign_[2]*(5.25 - 7.5*in[0]- 6.0*in[1] + 7.5*in[0]*in[0]); out[7][0][0] = 0.0; out[7][0][1] = 0.0; out[7][1][0] = 6.0 - 6.0*in[1]; out[7][1][1] = 3.0 - 6.0*in[0]; out[8][0][0] = sign_[2]*(-3.75 + 22.5*in[0] - 22.5*in[0]*in[0]); out[8][0][1] = 0.0; out[8][1][0] = sign_[2]*(22.5 - 22.5*in[1] - 45.0*in[0] + 45.0*in[0]*in[1]); out[8][1][1] = sign_[2]*(3.75 - 22.5*in[0] + 22.5*in[0]*in[0]); out[9][0][0] = sign_[3]*(-1.25 + 7.5*in[0] - 7.5*in[0]*in[0]); out[9][0][1] = 0.0; out[9][1][0] = sign_[3]*(-7.5*in[1] + 15.0*in[0]*in[1]); out[9][1][1] = sign_[3]*(-0.75 - 7.5*in[0] + 6.0*in[1] + 7.5*in[0]*in[0]); out[10][0][0] = 0.0; out[10][0][1] = 0.0; out[10][1][0] = 6.0*in[1]; out[10][1][1] = -3.0 + 6.0*in[0]; out[11][0][0] = sign_[3]*(-3.75 + 22.5*in[0] - 22.5*in[0]*in[0]); out[11][0][1] = 0.0; out[11][1][0] = sign_[3]*(-22.5*in[1] + 45*in[0]*in[1]); out[11][1][1] = sign_[3]*(3.75 - 22.5*in[0] + 22.5*in[0]*in[0]); out[12][0][0] = 6.0 - 12.0*in[0]; out[12][0][1] = 0.0; out[12][1][0] = 0.0; out[12][1][1] = 0.0; out[13][0][0] = 0.0; out[13][0][1] = 0.0; out[13][1][0] = 0.0; out[13][1][1] = 6.0 - 12.0*in[1]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0][0] = sign_[0]*(5.25 - 7.5*in[1] - 6.0*in[0] + 7.5*in[1]*in[1]); out[0][1] = 0.0; out[1][0] = -3.0 + 6.0*in[1]; out[1][1] = 0.0; out[2][0] = sign_[0]*(3.75 - 22.5*in[1] + 22.5*in[1]*in[1]); out[2][1] = 0.0; out[3][0] = sign_[1]*(-0.75 - 7.5*in[1] + 6.0*in[0] + 7.5*in[1]*in[1]); out[3][1] = 0.0; out[4][0] = 3.0 - 6.0*in[1]; out[4][1] = 0.0; out[5][0] = sign_[1]*(3.75 - 22.5*in[1] + 22.5*in[1]*in[1]); out[5][1] = 0.0; out[6][0] = sign_[2]*(-1.25 + 7.5*in[0] - 7.5*in[0]*in[0]); out[6][1] = sign_[2]*(7.5 - 7.5*in[1] - 15.0*in[0] + 15.0*in[0]*in[1]); out[7][0] = 0.0; out[7][1] = 6.0 - 6.0*in[1]; out[8][0] = sign_[2]*(-3.75 + 22.5*in[0] - 22.5*in[0]*in[0]); out[8][1] = sign_[2]*(22.5 - 22.5*in[1] - 45.0*in[0] + 45.0*in[0]*in[1]); out[9][0] = sign_[3]*(-1.25 + 7.5*in[0] - 7.5*in[0]*in[0]); out[9][1] = sign_[3]*(-7.5*in[1] + 15.0*in[0]*in[1]); out[10][0] = 0.0; out[10][1] = 6.0*in[1]; out[11][0] = sign_[3]*(-3.75 + 22.5*in[0] - 22.5*in[0]*in[0]); out[11][1] = sign_[3]*(-22.5*in[1] + 45*in[0]*in[1]); out[12][0] = 6.0 - 12.0*in[0]; out[12][1] = 0.0; out[13][0] = 0.0; out[13][1] = 0.0; break; case 1: out[0][0] = sign_[0]*(7.5 - 7.5*in[0] - 15.0*in[1] + 15.0*in[0]*in[1]); out[0][1] = sign_[0]*(-1.25 + 7.5*in[1] - 7.5*in[1]*in[1]); out[1][0] = -6.0 + 6.0*in[0]; out[1][1] = 0.0; out[2][0] = sign_[0]*(22.5 - 22.5*in[0] - 45.0*in[1] + 45.0*in[0]*in[1]); out[2][1] = sign_[0]*(-3.75 + 22.5*in[1] - 22.5*in[1]*in[1]); out[3][0] = sign_[1]*(-7.5*in[0] + 15.0*in[0]*in[1]); out[3][1] = sign_[1]*(-1.25 + 7.5*in[1] - 7.5*in[1]*in[1]); out[4][0] = -6.0*in[0]; out[4][1] = 0.0; out[5][0] = sign_[1]*(-22.5*in[0] + 45.0*in[0]*in[1]); out[5][1] = sign_[1]*(-3.75 + 22.5*in[1] - 22.5*in[1]*in[1]); out[6][0] = 0.0; out[6][1] = sign_[2]*(5.25 - 7.5*in[0]- 6.0*in[1] + 7.5*in[0]*in[0]); out[7][0] = 0.0; out[7][1] = 3.0 - 6.0*in[0]; out[8][0] = 0.0; out[8][1] = sign_[2]*(3.75 - 22.5*in[0] + 22.5*in[0]*in[0]); out[9][0] = 0.0; out[9][1] = sign_[3]*(-0.75 - 7.5*in[0] + 6.0*in[1] + 7.5*in[0]*in[0]); out[10][0] = 0.0; out[10][1] = -3.0 + 6.0*in[0]; out[11][0] = 0.0; out[11][1] = sign_[3]*(3.75 - 22.5*in[0] + 22.5*in[0]*in[0]); out[12][0] = 0.0; out[12][1] = 0.0; out[13][0] = 0.0; out[13][1] = 6.0 - 12.0*in[1]; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order() const { return 3; } private: std::array sign_; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALBASIS_HH brezzidouglasmarini2cube2dlocalcoefficients.hh000066400000000000000000000024161313314431100440570ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \brief Layout map for Brezzi-Douglas-Marini-2 elements on quadrilaterals * * \ingroup LocalLayoutImplementation * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class BDM2Cube2DLocalCoefficients { public: //! \brief Standard constructor BDM2Cube2DLocalCoefficients() : li(14) { for (std::size_t i = 0; i < 4; ++i) { li[3 * i] = LocalKey(i,1,0); li[3 * i + 1] = LocalKey(i,1,1); li[3 * i + 2] = LocalKey(i,1,2); } li[12] = LocalKey(0,0,0); li[13] = LocalKey(0,0,1); } //! \brief number of coefficients std::size_t size() const { return 14; } //! \brief get i'th index const LocalKey& localKey(std::size_t i) const { return li[i]; } private: std::vector li; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALCOEFFICIENTS_HH brezzidouglasmarini2cube2dlocalinterpolation.hh000066400000000000000000000103371313314431100443060ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \brief First order Brezzi-Douglas-Marini shape functions on quadrilaterals. * * \tparam LB corresponding LocalBasis giving traits * * \ingroup LocalInterpolationImplementation * \nosubgrouping */ template class BDM2Cube2DLocalInterpolation { public: //! \brief Standard constructor BDM2Cube2DLocalInterpolation() { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ BDM2Cube2DLocalInterpolation(unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } if (s & 8) { sign3 = -1.0; } n0[0] = -1.0; n0[1] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n3[0] = 0.0; n3[1] = 1.0; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate(const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(14); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const QuadratureRule& rule = QuadratureRules::rule(GeometryType(GeometryType::cube,1), qOrder); for (typename QuadratureRule::const_iterator it = rule.begin(); it != rule.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0; out[1] += (y[0]*n0[0] + y[1]*n0[1])*(2.0*qPos - 1.0)*it->weight(); out[2] += (y[0]*n0[0] + y[1]*n0[1])*(8.0*qPos*qPos - 8.0*qPos + 1.0)*it->weight()*sign0; localPos[0] = 1.0; localPos[1] = qPos; f.evaluate(localPos, y); out[3] += (y[0]*n1[0]+y[1]*n1[1])*it->weight()*sign1; out[4] += (y[0]*n1[0]+y[1]*n1[1])*(1.0 - 2.0*qPos)*it->weight(); out[5] += (y[0]*n1[0]+y[1]*n1[1])*(8.0*qPos*qPos - 8.0*qPos + 1.0)*it->weight()*sign1; localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[6] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2; out[7] += (y[0]*n2[0] + y[1]*n2[1])*(1.0 - 2.0*qPos)*it->weight(); out[8] += (y[0]*n2[0] + y[1]*n2[1])*(8.0*qPos*qPos - 8.0*qPos + 1.0)*it->weight()*sign2; localPos[0] = qPos; localPos[1] = 1.0; f.evaluate(localPos, y); out[9] += (y[0]*n3[0] + y[1]*n3[1])*it->weight()*sign3; out[10] += (y[0]*n3[0] + y[1]*n3[1])*(2.0*qPos - 1.0)*it->weight(); out[11] += (y[0]*n3[0] + y[1]*n3[1])*(8.0*qPos*qPos - 8.0*qPos + 1.0)*it->weight()*sign3; } const QuadratureRule& rule2 = QuadratureRules::rule(GeometryType(GeometryType::cube,2), qOrder); for (typename QuadratureRule::const_iterator it=rule2.begin(); it!=rule2.end(); ++it) { f.evaluate(it->position(), y); out[12] += y[0]*it->weight(); out[13] += y[1]*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2, sign3; typename LB::Traits::DomainType n0, n1, n2, n3; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d.hh000066400000000000000000000044231313314431100340510ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "brezzidouglasmarini2simplex2d/brezzidouglasmarini2simplex2dlocalbasis.hh" #include "brezzidouglasmarini2simplex2d/brezzidouglasmarini2simplex2dlocalcoefficients.hh" #include "brezzidouglasmarini2simplex2d/brezzidouglasmarini2simplex2dlocalinterpolation.hh" namespace Dune { /** * \brief Second order Brezzi-Douglas-Marini shape functions on triangles. * * \ingroup BrezziDouglasMarini * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class BDM2Simplex2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< BDM2Simplex2DLocalBasis, BDM2Simplex2DLocalCoefficients, BDM2Simplex2DLocalInterpolation > > Traits; //! \brief Standard constructor BDM2Simplex2DLocalFiniteElement () { gt.makeTriangle(); } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ BDM2Simplex2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeTriangle(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: BDM2Simplex2DLocalBasis basis; BDM2Simplex2DLocalCoefficients coefficients; BDM2Simplex2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d/000077500000000000000000000000001313314431100335255ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004251313314431100362070ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2dinstall(FILES brezzidouglasmarini2simplex2dlocalbasis.hh brezzidouglasmarini2simplex2dlocalcoefficients.hh brezzidouglasmarini2simplex2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d) brezzidouglasmarini2simplex2dlocalbasis.hh000066400000000000000000000220671313314431100440310ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALBASIS_HH #include #include #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief First order Brezzi-Douglas-Marini shape functions on quadrilaterals. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class BDM2Simplex2DLocalBasis { public: typedef LocalBasisTraits, R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor BDM2Simplex2DLocalBasis() { for (size_t i=0; i<3; i++) sign_[i] = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ BDM2Simplex2DLocalBasis(std::bitset<3> s) { for (size_t i=0; i<3; i++) sign_[i] = s[i] ? -1.0 : 1.0; } //! \brief number of shape functions unsigned int size() const { return 12; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); out[0][0] = sign_[0]*(-2*in[0]*in[1] + in[0]*in[0]); out[0][1] = sign_[0]*(-1 + 6*in[1] -2*in[0]*in[1] - 5*in[1]*in[1]); out[1][0] = 1.5*in[0] + 3*in[0]*in[1] - 4.5*in[0]*in[0]; out[1][1] = -3 + 6*in[0] + 10.5*in[1] - 15*in[0]*in[1] - 7.5*in[1]*in[1]; out[2][0] = sign_[0]*(-7.5*in[0] + 5*in[0]*in[1] + 12.5*in[0]*in[0]); out[2][1] = sign_[0]*(-5 + 30*in[0] + 7.5*in[1] - 25*in[0]*in[1] - 30*in[0]*in[0] - 2.5*in[1]*in[1]); out[3][0] = sign_[1]*(-1 + 6*in[0] - 2*in[0]*in[1] - 5*in[0]*in[0]); out[3][1] = sign_[1]*(-2*in[0]*in[1] + in[1]*in[1]); out[4][0] = 3 - 10.5*in[0] - 6*in[1] + 15*in[0]*in[1] + 7.5*in[0]*in[0]; out[4][1] = -1.5*in[1] - 3*in[0]*in[1] + 4.5*in[1]*in[1]; out[5][0] = sign_[1]*(-5 + 7.5*in[0] + 30*in[1] - 25*in[0]*in[1] - 2.5*in[0]*in[0] - 30*in[1]*in[1]); out[5][1] = sign_[1]*(-7.5*in[1] + 5*in[0]*in[1] + 12.5*in[1]*in[1]); out[6][0] = sign_[2]*(-3*in[0] + 4*in[0]*in[1] + 4*in[0]*in[0]); out[6][1] = sign_[2]*(-3*in[1] + 4*in[0]*in[1] + 4*in[1]*in[1]); out[7][0] = -3*in[0] + 6*in[0]*in[0]; out[7][1] = 3*in[1] - 6*in[1]*in[1]; out[8][0] = sign_[2]*(-10*in[0]*in[1] + 5*in[0]*in[0]); out[8][1] = sign_[2]*(-10*in[0]*in[1] + 5*in[1]*in[1]); out[9][0] = 18*in[0] - 12*in[0]*in[1] - 18*in[0]*in[0]; out[9][1] = 6*in[1] - 12*in[0]*in[1] - 6*in[1]*in[1]; out[10][0] = 6*in[0] - 12*in[0]*in[1] - 6*in[0]*in[0]; out[10][1] = 18*in[1] - 12*in[0]*in[1] - 18*in[1]*in[1]; out[11][0] = 90*in[0] - 180*in[0]*in[1] - 90*in[0]*in[0]; out[11][1] = -90*in[1] + 180*in[0]*in[1] + 90*in[1]*in[1]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); out[0][0][0] = sign_[0]*(-2*in[1] + 2*in[0]); out[0][0][1] = sign_[0]*(-2*in[0]); out[0][1][0] = sign_[0]*(-2*in[1]); out[0][1][1] = sign_[0]*(6 -2*in[0] - 10*in[1]); out[1][0][0] = 1.5 + 3*in[1] - 9*in[0]; out[1][0][1] = 3*in[0]; out[1][1][0] = 6 - 15*in[1]; out[1][1][1] = 10.5 - 15*in[0] - 15*in[1]; out[2][0][0] = sign_[0]*(-7.5 + 5*in[1] + 25*in[0]); out[2][0][1] = sign_[0]*(5*in[0]); out[2][1][0] = sign_[0]*(30 - 25*in[1] - 60*in[0]); out[2][1][1] = sign_[0]*(7.5 - 25*in[0] - 5*in[1]); out[3][0][0] = sign_[1]*(6 - 2*in[1] - 10*in[0]); out[3][0][1] = sign_[1]*(-2*in[0]); out[3][1][0] = sign_[1]*(-2*in[1]); out[3][1][1] = sign_[1]*(-2*in[0] + 2*in[1]); out[4][0][0] = -10.5 + 15*in[1] + 15*in[0]; out[4][0][1] = -6 + 15*in[0]; out[4][1][0] = -3*in[1]; out[4][1][1] = -1.5 - 3*in[0] + 9*in[1]; out[5][0][0] = sign_[1]*(7.5 - 25*in[1] - 5*in[0]); out[5][0][1] = sign_[1]*(30 - 25*in[0] - 60*in[1]); out[5][1][0] = sign_[1]*(5*in[1]); out[5][1][1] = sign_[1]*(-7.5 + 5*in[0] + 25*in[1]); out[6][0][0] = sign_[2]*(-3 + 4*in[1] + 8*in[0]); out[6][0][1] = sign_[2]*(4*in[0]); out[6][1][0] = sign_[2]*(4*in[1]); out[6][1][1] = sign_[2]*(-3 + 4*in[0] + 8*in[1]); out[7][0][0] = -3 + 12*in[0]; out[7][0][1] = 0; out[7][1][0] = 0; out[7][1][1] = 3 - 12*in[1]; out[8][0][0] = sign_[2]*(-10*in[1] + 10*in[0]); out[8][0][1] = sign_[2]*(-10*in[0]); out[8][1][0] = sign_[2]*(-10*in[1]); out[8][1][1] = sign_[2]*(-10*in[0] + 10*in[1]); out[9][0][0] = 18 - 12*in[1] - 36*in[0]; out[9][0][1] = -12*in[0]; out[9][1][0] = -12*in[1]; out[9][1][1] = 6 - 12*in[0] - 12*in[1]; out[10][0][0] = 6 - 12*in[1] - 12*in[0]; out[10][0][1] = -12*in[0]; out[10][1][0] = -12*in[1]; out[10][1][1] = 18 - 12*in[0] - 36*in[1]; out[11][0][0] = 90 - 180*in[1] - 180*in[0]; out[11][0][1] = -180*in[0]; out[11][1][0] = 180*in[1]; out[11][1][1] = -90 + 180*in[0] + 180*in[1]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0][0] = sign_[0]*(-2*in[1] + 2*in[0]); out[0][1] = sign_[0]*(-2*in[1]); out[1][0] = 1.5 + 3*in[1] - 9*in[0]; out[1][1] = 6 - 15*in[1]; out[2][0] = sign_[0]*(-7.5 + 5*in[1] + 25*in[0]); out[2][1] = sign_[0]*(30 - 25*in[1] - 60*in[0]); out[3][0] = sign_[1]*(6 - 2*in[1] - 10*in[0]); out[3][1] = sign_[1]*(-2*in[1]); out[4][0] = -10.5 + 15*in[1] + 15*in[0]; out[4][1] = -3*in[1]; out[5][0] = sign_[1]*(7.5 - 25*in[1] - 5*in[0]); out[5][1] = sign_[1]*(5*in[1]); out[6][0] = sign_[2]*(-3 + 4*in[1] + 8*in[0]); out[6][1] = sign_[2]*(4*in[1]); out[7][0] = -3 + 12*in[0]; out[7][1] = 0; out[8][0] = sign_[2]*(-10*in[1] + 10*in[0]); out[8][1] = sign_[2]*(-10*in[1]); out[9][0] = 18 - 12*in[1] - 36*in[0]; out[9][1] = -12*in[1]; out[10][0] = 6 - 12*in[1] - 12*in[0]; out[10][1] = -12*in[1]; out[11][0] = 90 - 180*in[1] - 180*in[0]; out[11][1] = 180*in[1]; break; case 1: out[0][0] = sign_[0]*(-2*in[0]); out[0][1] = sign_[0]*(6 -2*in[0] - 10*in[1]); out[1][0] = 3*in[0]; out[1][1] = 10.5 - 15*in[0] - 15*in[1]; out[2][0] = sign_[0]*(5*in[0]); out[2][1] = sign_[0]*(7.5 - 25*in[0] - 5*in[1]); out[3][0] = sign_[1]*(-2*in[0]); out[3][1] = sign_[1]*(-2*in[0] + 2*in[1]); out[4][0] = -6 + 15*in[0]; out[4][1] = -1.5 - 3*in[0] + 9*in[1]; out[5][0] = sign_[1]*(30 - 25*in[0] - 60*in[1]); out[5][1] = sign_[1]*(-7.5 + 5*in[0] + 25*in[1]); out[6][0] = sign_[2]*(4*in[0]); out[6][1] = sign_[2]*(-3 + 4*in[0] + 8*in[1]); out[7][0] = 0; out[7][1] = 3 - 12*in[1]; out[8][0] = sign_[2]*(-10*in[0]); out[8][1] = sign_[2]*(-10*in[0] + 10*in[1]); out[9][0] = -12*in[0]; out[9][1] = 6 - 12*in[0] - 12*in[1]; out[10][0] = -12*in[0]; out[10][1] = 18 - 12*in[0] - 36*in[1]; out[11][0] = -180*in[0]; out[11][1] = -90 + 180*in[0] + 180*in[1]; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order() const { return 2; // TODO: check whether this is not order 3 } private: std::array sign_; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALBASIS_HH brezzidouglasmarini2simplex2dlocalcoefficients.hh000066400000000000000000000025641313314431100453710ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \brief Layout map for Brezzi-Douglas-Marini-2 elements on triangles. * * \ingroup LocalLayoutImplementation * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class BDM2Simplex2DLocalCoefficients { public: //! \brief Standard constructor BDM2Simplex2DLocalCoefficients() : li(12) { for (std::size_t i = 0; i < 3; ++i) { li[3 * i] = LocalKey(i,1,0); li[3 * i + 1] = LocalKey(i,1,1); li[3 * i + 2] = LocalKey(i,1,2); } // last DOFs are associated with the cell (codim=0) li[9] = LocalKey(0,0,0); li[10] = LocalKey(0,0,1); li[11] = LocalKey(0,0,2); } //! \brief number of coefficients std::size_t size() const { return 12; } //! \brief get i'th index const LocalKey& localKey(std::size_t i) const { return li[i]; } private: std::vector li; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALCOEFFICIENTS_HH brezzidouglasmarini2simplex2dlocalinterpolation.hh000066400000000000000000000107421313314431100456140ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \brief First order Brezzi-Douglas-Marini shape functions on triangles. * * \tparam LB corresponding LocalBasis giving traits * * \ingroup LocalInterpolationImplementation * \nosubgrouping */ template class BDM2Simplex2DLocalInterpolation { public: //! \brief Standard constructor BDM2Simplex2DLocalInterpolation() { sign0 = sign1 = sign2 = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ BDM2Simplex2DLocalInterpolation(unsigned int s) { sign0 = sign1 = sign2 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } m0[0] = 0.5; m0[1] = 0.0; m1[0] = 0.0; m1[1] = 0.5; m2[0] = 0.5; m2[1] = 0.5; n0[0] = 0.0; n0[1] = -1.0; n1[0] = -1.0; n1[1] = 0.0; n2[0] = 1.0/sqrt(2.0); n2[1] = 1.0/sqrt(2.0); c0 = 0.5*n0[0] - 1.0*n0[1]; c1 = -1.0*n1[0] + 0.5*n1[1]; c2 = 0.5*n2[0] + 0.5*n2[1]; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate(const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(12); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const Dune::QuadratureRule& rule = Dune::QuadratureRules::rule(Dune::GeometryType(Dune::GeometryType::simplex,1), qOrder); for (typename Dune::QuadratureRule::const_iterator it=rule.begin(); it!=rule.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0/c0; out[1] += (y[0]*n0[0] + y[1]*n0[1])*(1.0 - 2.0*qPos)*it->weight()/c0; out[2] += (y[0]*n0[0] + y[1]*n0[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign0/c0; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[3] += (y[0]*n1[0]+y[1]*n1[1])*it->weight()*sign1/c1; out[4] += (y[0]*n1[0]+y[1]*n1[1])*(2.0*qPos-1.0)*it->weight()/c1; out[5] += (y[0]*n1[0]+y[1]*n1[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign1/c1; localPos[0] = 1.0 - qPos; localPos[1] = qPos; f.evaluate(localPos, y); out[6] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2/c2; out[7] += (y[0]*n2[0] + y[1]*n2[1])*(1.0 - 2.0*qPos)*it->weight()/c2; out[8] += (y[0]*n2[0] + y[1]*n2[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign2/c2; } // a volume part is needed here for dofs: 9 10 11 const QuadratureRule& rule2 = QuadratureRules::rule(GeometryType(GeometryType::simplex,2), qOrder); for (typename QuadratureRule::const_iterator it=rule2.begin(); it!=rule2.end(); ++it) { typename LB::Traits::DomainType localPos = it->position(); f.evaluate(localPos, y); out[9] += y[0]*it->weight(); out[10] += y[1]*it->weight(); out[11] += (y[0]*(localPos[0]-2.0*localPos[0]*localPos[1]-localPos[0]*localPos[0]) +y[1]*(-localPos[1]+2.0*localPos[0]*localPos[1]+localPos[1]*localPos[1]))*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2; typename LB::Traits::DomainType m0, m1, m2; typename LB::Traits::DomainType n0, n1, n2; typename LB::Traits::RangeFieldType c0, c1, c2; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/common/000077500000000000000000000000001313314431100227335ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/common/CMakeLists.txt000066400000000000000000000003721313314431100254750ustar00rootroot00000000000000install(FILES interface.hh interfaceswitch.hh localbasis.hh localkey.hh localfiniteelementtraits.hh localtoglobaladaptors.hh virtualinterface.hh virtualwrappers.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/common) dune-localfunctions-2.5.1/dune/localfunctions/common/interface.hh000066400000000000000000000242021313314431100252140ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_INTERFACE_HH #define DUNE_LOCALFUNCTIONS_INTERFACE_HH #ifndef HEADERCHECK #error This header exists for documentation purposes only and should never be included directly. #endif #include #include #include #include #include namespace Dune { //! Interface for global-valued finite elements class FiniteElementInterface { struct ImplementationDefined; public: //! types of component objects /** * \note This may be a typedef instead of a member class. */ struct Traits { //! type of the Basis /** * Should be an implementation of BasisInterface * * \note May be an inline class instead of a typedef. */ typedef ImplementationDefined Basis; //! type of the Coefficients /** * Should be an implementation of CoefficientsInterface * * \note May be an inline class instead of a typedef. */ typedef ImplementationDefined Coefficients; //! type of the Interpolation /** * Should be an implementation of InterpolationInterface * * \note May be an inline class instead of a typedef. */ typedef ImplementationDefined Interpolation; }; //! Construct a finite element /** * \note The arguments of the constructor are implementation specific. In * fact, finite element implementations are not required to be * constructible by the user at all (except for copy-construction). * The official way to construct a finite element is to use its * factory. */ FiniteElementInterface(...); //! Finite elements are CopyConstructible FiniteElementInterface(const FiniteElementInterface&); //! Extract basis of this finite element /** * The returned lvalue must have a lifetime at least as long as the finite * element object it was acquired from. */ const Traits::Basis& basis() const; //! Extract coefficients of this finite element /** * The returned lvalue must have a lifetime at least as long as the finite * element object it was acquired from. */ const Traits::Coefficients& coefficients() const; //! Extract interpolation of this finite element /** * The returned lvalue must have a lifetime at least as long as the finite * element object it was acquired from. */ const Traits::Interpolation& interpolation() const; //! Extract geometry type of this finite element GeometryType type() const; }; //! Factory interface for global-valued finite elements /** * The main purpose of the factory class is to provide a concept for * caching. Take for instance a global-valued finite element that wraps a * local finite element. The local finite element will typically have very * few variants, and the global-valued finite element will just apply a * geometric transformation to the derivatives. The wrapped local finite * elements can be stored inside the factory and any global-valued finite * elements created by the factory just contain references or pointers. * This way the local finite elements don't need to be created anew for each * global-valued finite element. * * The other purpose is to semi-standardize the interface used to actually * create finite elements. "Semi" because the information needed to create * an actual global-valued finite element will vary between finite element * types. There are however certain types of information that are needed by * a larger subset of all available finite elements, so it makes sense to * define a common encoding for these types of information. On the other * hand this information is often expensive to obtain, so it makes sense to * only provide it when it is actually needed. */ template class FiniteElementFactoryInterface { struct ImplementationDefined; public: //! Type of the finite element /** * Should be an implementation of FiniteElementInterface * * \note May be an inline class instead of a typedef. */ typedef ImplementationDefined FiniteElement; //! Construct a finite element factory /** * \note The arguments of the constructor are implementation specific. */ FiniteElementFactoryInterface(...); /** \name Finite element creation methods * * Each finite element factory implementation must provide at least one of * these methods. The signatures may be extended by additional * parameters, but the parameters that are specified here should be given * first and in the order specified here. * * The return value of these functions is suitable for binding to a const * reference -- it will either be an rvalue (in which case binding to a * const reference will create a copy whose lifetime is the same as the * reference itself), or it will be an lvalue (in which case the factory * must guarantee that it will be valid until the factory is destroyed or * something else happens that explicitly invalidates all created finite * elements). * * In any case, since global-valued finite element objects are * copy-constructible, it is also possible to use the returned value to * initialize a finite element object instead of a const reference. */ //! \{ //! create a finite element from a geometry and a vertex ordering const FiniteElement make(const Geometry&, const VertexOrder&, ...); //! create a finite element from a geometry const FiniteElement make(const Geometry&, ...); //! create a finite element from a vertex ordering const FiniteElement make(const VertexOrder&, ...); //! create a finite element from a geometry type /** * \note This signature should only be used when only the geometry type * but not the full geometry or vertex ordering are needed. */ const FiniteElement make(const GeometryType&, ...); //! create a finite element const FiniteElement make(...); //! \} }; //! Interface for global-valued shape functions class BasisInterface { struct ImplementationDefined; enum { implementationDefined }; public: //! types of domain and range /** * \nosubgrouping * * \note This may be a typedef instead of a member class. */ struct Traits { //! \name Domain properties (local and global) //! \{ //! Field type of the domain typedef ImplementationDefined DomainField; //! Dimension of the local coordinate system static const std::size_t dimDomainLocal = implementationDefined; //! Dimension of the world coordinate system static const std::size_t dimDomainGlobal = implementationDefined; //! Type used for coordinate vectors in the local domain typedef ImplementationDefined DomainLocal; //! Type used for coordinate vectors in the world domain typedef ImplementationDefined DomainGlobal; //! \} //! \name Range properties (global range only) //! \{ //! Field type of the range typedef ImplementationDefined RangeField; //! Dimension of the range values static const std::size_t dimRange = implementationDefined; //! Type used for range values typedef ImplementationDefined Range; //! \} //! Jacobian properties /** * \note The Jacobian should be some matrix type with \c dimRange x * \c dimDomainGlobal components of type \c RangeField. */ typedef ImplementationDefined Jacobian; //! maximum number of partial derivatives supported static const std::size_t diffOrder = implementationDefined; }; //! Number of shape functions std::size_t size () const; //! Polynomial order of the shape functions for quadrature std::size_t order () const; //! Evaluate all shape functions at given position void evaluateFunction(const Traits::DomainLocal& in, std::vector& out) const; //! Evaluate Jacobian of all shape functions at given position /** * Note: Only required for Traits::diffOrder >= 1 */ void evaluateJacobian(const Traits::DomainLocal& in, std::vector& out) const; //! Evaluate derivatives of all shape functions at given position /** * \note Only required for Traits::diffOrder >= 2 */ void evaluate ( const std::array& directions, const Traits::DomainLocal& in, std::vector& out) const; }; //! Interface for global-valued interpolation struct InterpolationInterface { //! Export basis traits /** * This should be the traits class of the corresponding basis. */ typedef BasisInterface::Traits Traits; //! Determine coefficients interpolating a given function /** * \param f An object supporting the expression \c f.evaluate(x,y), * where \c x is of type \c Traits::DomainLocal and \c y of the * type \c Traits::Range. When \c f.evaluate(x,y) is * evaluated, \c x will be a local coordinate , and the * expression should set \c y to the function value at that * position. The initial value of \c y should not be used. * \param out Vector where to store the interpolated coefficients. */ template void interpolate (const F& f, std::vector& out) const; }; //! Interface for global-valued coefficients /** * \note This interface is listed separately only to keep it together with * the other global-valued interfaces. It is identical to the * interface for local coefficients. */ struct CoefficientsInterface { //! number of coefficients std::size_t size() const; //! get i'th index const LocalKey& localKey(std::size_t i) const; }; } #endif // DUNE_LOCALFUNCTIONS_INTERFACE_HH dune-localfunctions-2.5.1/dune/localfunctions/common/interfaceswitch.hh000066400000000000000000000225221313314431100264410ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_COMMON_INTERFACESWITCH_HH #define DUNE_LOCALFUNCTIONS_COMMON_INTERFACESWITCH_HH #include #include #include #include #include namespace Dune { //! \brief Switch for uniform treatment of finite element with either the //! local or the global interface /** * \tparam FiniteElement Type of the finite element to handle. * \tparam Dummy Dummy parameter for enable_if. This must be left * at the default value of \c void. * * \note The local interface is detected by the presence of the type * FiniteElement::Traits::LocalBasisType. */ template struct FiniteElementInterfaceSwitch { //! export the type of the basis typedef typename FiniteElement::Traits::Basis Basis; //! export the type of the interpolation typedef typename FiniteElement::Traits::Interpolation Interpolation; //! export the type of the coefficients typedef typename FiniteElement::Traits::Coefficients Coefficients; //! access basis static const Basis &basis(const FiniteElement& fe) { return fe.basis(); } //! access interpolation static const Interpolation &interpolation(const FiniteElement& fe) { return fe.interpolation(); } //! access coefficients static const Coefficients &coefficients(const FiniteElement& fe) { return fe.coefficients(); } //! Type for storing finite elements /** * Some algorithms use one variable to store (a pointer) a finite element * and update that pointer while iterating through the grid. This works * well for local finite elements, since they exists in a finite number of * variants, which can be stored somewhere and don't need to change for * the duration of the algorithm, so we can always store a simple pointer. * For global finite elements we have to store the object itself however, * and we must make sure that we destroy the object when we are done with * it. Since global finite elements are not assignable in general, we * needs to copy-construct them for each grid element we visit. * * To accommodate both interfaces, we define a store: for local finite * elements it is a simple pointer, and if we want to store a finite * element in it we simply store its address. For global finite elements * we use a shared_ptr, and if we want to store a finite element in it we * allocate a new object and initialise it with the copy-constructor. For * local finite elements we don't need to do anything when we are done * with it, global finite elements are automatically destructed by the * shared_ptr when we store a new one or when the shared_ptr itself is * destroyed. Access to the finite element is done by simply * dereferencing the store in both cases. */ typedef std::shared_ptr Store; //! Store a finite element in the store. /** * For local finite elements this means storing the address of the passed * reference, for global finite element this means creating a new object * with allocation and copy-construction and storing that. */ static void setStore(Store& store, const FiniteElement& fe) { store.reset(new FiniteElement(fe)); } }; #ifndef DOXYGEN //! \brief Switch for uniform treatment of finite element with either the //! local or the global interface template struct FiniteElementInterfaceSwitch< FiniteElement, typename std::enable_if::value>::type > { //! export the type of the basis typedef typename FiniteElement::Traits::LocalBasisType Basis; //! export the type of the interpolation typedef typename FiniteElement::Traits::LocalInterpolationType Interpolation; //! export the type of the coefficients typedef typename FiniteElement::Traits::LocalCoefficientsType Coefficients; //! access basis static const Basis &basis(const FiniteElement& fe) { return fe.localBasis(); } //! access interpolation static const Interpolation &interpolation(const FiniteElement& fe) { return fe.localInterpolation(); } //! access coefficients static const Coefficients &coefficients(const FiniteElement& fe) { return fe.localCoefficients(); } //! Type for storing finite elements typedef const FiniteElement *Store; //! Store a finite element in the store. static void setStore(Store& store, const FiniteElement& fe) { store = &fe; } }; #endif // !DOXYGEN //! Switch for uniform treatment of local and global basis classes /** * \tparam Basis Type of the basis to handle. * \tparam Dummy Dummy parameter for enable_if. This must be left at the * default value of \c void. * * We don't provide any uniform access to the types and constants pertaining * to the global domain. Providing this would require the Geometry as * template parameter as well, and the user code can build them itself if it * needs them with the help of the geometry. The omitted types are \c * DomainGlobal and \c Jacobian, the omitted constant is \c dimDomainGlobal. * * \note The local interface is assumed if the constant * Basis::Traits::dimDomain exists and has a value greater than 0. */ template struct BasisInterfaceSwitch { //! export field types of the coordinates typedef typename Basis::Traits::DomainField DomainField; //! export dimension of local coordinates static const std::size_t dimDomainLocal = Basis::Traits::dimDomainLocal; //! export vector type of the local coordinates typedef typename Basis::Traits::DomainLocal DomainLocal; //! export field type of the values typedef typename Basis::Traits::RangeField RangeField; //! export dimension of the values static const std::size_t dimRange = Basis::Traits::dimRange; //! export vector type of the values typedef typename Basis::Traits::Range Range; //! export number of supported differentiations static const std::size_t diffOrder = Basis::Traits::diffOrder; //! Compute global gradient for scalar valued bases /** * \param basis The basis to get the derivatives from. * \param geometry The geometry to use to transform the derivatives (for a * local basis, unused in the case of a global basis). * \param xl The local coordinates where to evaluate the gradient. * \param grad The result (will be resized to the appropriate number * of entries. * * \note This make sense only for a scalar valued basis. */ template static void gradient(const Basis& basis, const Geometry& geometry, const DomainLocal& xl, std::vector >& grad) { grad.resize(basis.size()); basis.evaluateJacobian(xl, grad); } }; #ifndef DOXYGEN //! Switch for uniform treatment of local and global basis classes template struct BasisInterfaceSwitch >::value >::type > { //! export field types of the coordinates typedef typename Basis::Traits::DomainFieldType DomainField; //! export dimension of local coordinates static const std::size_t dimDomainLocal = Basis::Traits::dimDomain; //! export vector type of the local coordinates typedef typename Basis::Traits::DomainType DomainLocal; //! export field type of the values typedef typename Basis::Traits::RangeFieldType RangeField; //! export dimension of the values static const std::size_t dimRange = Basis::Traits::dimRange; //! export vector type of the values typedef typename Basis::Traits::RangeType Range; //! export number of supported differentiations static const std::size_t diffOrder = Basis::Traits::diffOrder; //! Compute global gradient for scalar valued bases template static void gradient(const Basis& basis, const Geometry& geometry, const DomainLocal& xl, std::vector >& grad) { std::vector lgrad(basis.size()); basis.evaluateJacobian(xl, lgrad); const typename Geometry::JacobianInverseTransposed& jac = geometry.jacobianInverseTransposed(xl); grad.resize(basis.size()); for(std::size_t i = 0; i < basis.size(); ++i) jac.mv(lgrad[i][0], grad[i][0]); } }; #endif // !DOXYGEN } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_COMMON_INTERFACESWITCH_HH dune-localfunctions-2.5.1/dune/localfunctions/common/localbasis.hh000066400000000000000000000123551313314431100253760ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALBASIS_HH #define DUNE_LOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisInterface \brief Type traits for LocalBasisVirtualInterface A shape function is a function \f[ \hat\phi : \mbox{IR}^n \to \mbox{IR}^m. \f] This traits class holds information how the signature of this function is represented in C++ types. This is just a convenience class for supplying traits to the LocalBasisVirtualInterface and its implementations. \tparam DF Type to represent the field in the domain. \tparam n Dimension of the domain. \tparam D Type to represent the domain, allows random access. \tparam RF Type to represent the field in the range. \tparam m Dimension of the range. \tparam R Type to represent the range, allows random access. \tparam J Type to represent the Jacobian, allows random access. \tparam dorder Maximal order of implemented partial derivatives \nosubgrouping */ template struct LocalBasisTraits { //! \brief Export type for domain field typedef DF DomainFieldType; //! \brief Enum for domain dimension enum { //! \brief dimension of the domain dimDomain = n }; //! \brief domain type typedef D DomainType; //! \brief Export type for range field typedef RF RangeFieldType; //! \brief Enum for range dimension enum { //! \brief dimension of the range dimRange = m }; //! \brief range type typedef R RangeType; /** \brief Type to represent derivative When \f$ \hat\phi : \mbox{IR}^n \to \mbox{IR}^m \f$ then JacobianType is an 2D-array of m x n components where entry J[i][j] contains the derivative \f$\partial_j \hat\phi_i \f$. */ typedef J JacobianType; //! \brief Enum for differentiability order enum { //! \brief number of partial derivatives supported diffOrder=dorder }; }; /**@ingroup LocalBasisInterface \brief Type traits for LocalBasisInterface A shape function is a function \f[ \hat\phi : \mbox{IR}^n \to \mbox{IR}^m. \f] This traits class holds information how the signature of this function is represented in C++ types. This is just a convenience class for supplying traits to the C0LocalBasisInterface. \tparam DF Type to represent the field in the domain. \tparam n Dimension of the domain. \tparam D Type to represent the domain, allows random access. \tparam RF Type to represent the field in the range. \tparam m Dimension of the range. \tparam R Type to represent the range, allows random access. \nosubgrouping */ template struct C0LocalBasisTraits { //! \brief Export type for domain field typedef DF DomainFieldType; //! \brief Enum for domain dimension enum { //! \brief dimension of the domain dimDomain = n }; //! \brief domain type typedef D DomainType; //! \brief Export type for range field typedef RF RangeFieldType; //! \brief Enum for range dimension enum { //! \brief dimension of the range dimRange = m }; //! \brief range type typedef R RangeType; //! \brief Enum for differentiability order enum { //! \brief number of derivatives supported diffOrder=0 }; }; /**@ingroup LocalBasisInterface \brief Type traits for C1LocalBasisInterface Extends the traits class LocalBasisTraits for differentiable shape functions. \tparam DF Type to represent the field in the domain. \tparam n Dimension of the domain. \tparam D Type to represent the domain, allows random access. \tparam RF Type to represent the field in the range. \tparam m Dimension of the range. \tparam R Type to represent the range, allows random access. \tparam J Type to represent the Jacobian, allows random access. \nosubgrouping */ template struct C1LocalBasisTraits : public C0LocalBasisTraits { /** \brief Type to represent derivative When \f$ \hat\phi : \mbox{IR}^n \to \mbox{IR}^m \f$ then JacobianType is an 2D-array of m x n components where entry J[i][j] contains the derivative \f$\partial_j \hat\phi_i \f$. */ typedef J JacobianType; //! \brief Enum for differentiability order enum { //! \brief number of derivatives supported diffOrder=1 }; }; template struct CkLocalBasisTraits : public C1LocalBasisTraits { //! \brief Enum for differentiability order enum { //! \brief number of derivatives supported diffOrder=dorder }; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/common/localfiniteelementtraits.hh000066400000000000000000000010401313314431100303410ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFINITEELEMENTTRAITS_HH #define DUNE_LOCALFINITEELEMENTTRAITS_HH namespace Dune { //! traits helper struct template struct LocalFiniteElementTraits { /** \todo Please doc me ! */ typedef LB LocalBasisType; /** \todo Please doc me ! */ typedef LC LocalCoefficientsType; /** \todo Please doc me ! */ typedef LI LocalInterpolationType; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/common/localkey.hh000066400000000000000000000054771313314431100250740ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALKEY_HH #define DUNE_LOCALKEY_HH #include #include #include namespace Dune { /**@ingroup LocalLayoutInterface \brief Describe position of one degree of freedom A LocalKey associates a degree of freedom with an index of a local basis function. \nosubgrouping */ class LocalKey { public: /** \brief Enumerate 'special values' for the codimension method */ enum { /** \brief Codimension returned by LocalKey::codim() for degrees of freedom attached to an intersection The standard interface of dune-localfunctions assumes that degrees of freedom are attached to subentities of an element. This subentities can be described by a codimension and a subentity number. However some elements, like the mimetic finite elements, attach their degrees of freedom to intersections. While intersections do have a codimension, namely 1, having the method codim() return 1 in this case would be ambiguous. Hence 'intersectionCodim' is returned instead. */ intersectionCodim=666 }; //! \brief Standard constructor for uninitialized local index LocalKey () {} /** \brief Initialize all components \param s Local number of the associated subentity \param c Codimension of the associated subentity \param i Index in the set of all functions associated to this subentity */ LocalKey (unsigned int s, unsigned int c, unsigned int i) { values_[0] = s; values_[1] = c; values_[2] = i; } //! \brief Return number of associated subentity inline unsigned int subEntity () const { return values_[0]; } //! \brief Return codim of associated entity inline unsigned int codim () const { return values_[1]; } //! \brief Return offset within subentity inline unsigned int index () const { return values_[2]; } //! \brief Set index component void index (unsigned int i) { values_[2] = i; } /** \brief Less-than operator so we can use this class as a key type in stl containers */ bool operator< (const LocalKey& other) const { return values_ < other.values_; } /** \brief Write LocalKey object to output stream */ friend std::ostream& operator<< (std::ostream& s, const LocalKey& localKey) { return s << "[ subEntity: " << localKey.subEntity() << ", codim: " << localKey.codim() << ", index: " << localKey.index() << " ]"; } private: // We use an array to store the values in order to be able to use the array::operator< implementation std::array values_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/common/localtoglobaladaptors.hh000066400000000000000000000255331313314431100276400ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_COMMON_LOCALTOGLOBALADAPTORS_HH #define DUNE_LOCALFUNCTIONS_COMMON_LOCALTOGLOBALADAPTORS_HH #include #include #include #include #include #include namespace Dune { //! Traits class for local-to-global basis adaptors /** * \tparam LocalBasisTraits Traits class of the LocalBasis to be adapted. * \tparam dimDomainGlobal_ Dimension of the global coordinates, * i.e. Geometry::coorddimension, if the global * coordinates are determined by a Geometry. * * \implements BasisInterface::Traits */ template struct LocalToGlobalBasisAdaptorTraits { typedef typename LocalBasisTraits::DomainFieldType DomainField; static const std::size_t dimDomainLocal = LocalBasisTraits::dimDomain; static const std::size_t dimDomainGlobal = dimDomainGlobal_; typedef typename LocalBasisTraits::DomainType DomainLocal; typedef FieldVector DomainGlobal; typedef typename LocalBasisTraits::RangeFieldType RangeField; static const std::size_t dimRange = LocalBasisTraits::dimRange; typedef typename LocalBasisTraits::RangeType Range; typedef FieldMatrix Jacobian; static const std::size_t diffOrder = LocalBasisTraits::diffOrder; }; //! Convert a simple scalar local basis into a global basis /** * The local basis must be scalar, i.e. LocalBasis::Traits::dimRange must be * 1. It's values are not transformed. * * For scalar function \f$f\f$, the gradient is equivalent to the transposed * Jacobian \f$\nabla f|_x = J_f^T(x)\f$. The Jacobian is thus transformed * using * \f[ * \nabla f|_{\mu(\hat x)} = * \hat J_\mu^{-T}(\hat x) \cdot \hat\nabla\hat f|_{\hat x} * \f] * Here the hat \f$\hat{\phantom x}\f$ denotes local quantities and * \f$\mu\f$ denotes the local-to-global map of the geometry. * * \tparam LocalBasis Type of the local basis to adapt. * \tparam Geometry Type of the local-to-global transformation. * * \implements BasisInterface */ template class ScalarLocalToGlobalBasisAdaptor { static_assert(LocalBasis::Traits::dimRange == 1, "ScalarLocalToGlobalBasisAdaptor can only wrap a " "scalar local basis."); static_assert((std::is_same::value), "ScalarLocalToGlobalBasisAdaptor: LocalBasis must use " "the same ctype as Geometry"); static_assert ( static_cast(LocalBasis::Traits::dimDomain) == static_cast(Geometry::mydimension), "ScalarLocalToGlobalBasisAdaptor: LocalBasis domain dimension must " "match local dimension of Geometry"); const LocalBasis& localBasis; Geometry geometry; public: typedef LocalToGlobalBasisAdaptorTraits Traits; //! construct a ScalarLocalToGlobalBasisAdaptor /** * \param localBasis_ The local basis object to adapt. * \param geometry_ The geometry object to use for adaption. * * \note This class stores the references passed here. Any use of this * class after these references have become invalid results in * undefined behaviour. The exception is that the destructor of * this class may still be called. */ ScalarLocalToGlobalBasisAdaptor(const LocalBasis& localBasis_, const Geometry& geometry_) : localBasis(localBasis_), geometry(geometry_) { } std::size_t size() const { return localBasis.size(); } //! return maximum polynomial order of the base function /** * This is to determine the required quadrature order. For an affine * geometry this is the same order as for the local basis. For other * geometries this returns the order of the local basis plus the global * dimension minus 1. The assumtion for non-affine geometries is that * they are still multi-linear. */ std::size_t order() const { if(geometry.affine()) // affine linear return localBasis.order(); else // assume at most order dim return localBasis.order() + Traits::dimDomainGlobal - 1; } void evaluateFunction(const typename Traits::DomainLocal& in, std::vector& out) const { localBasis.evaluateFunction(in, out); } void evaluateJacobian(const typename Traits::DomainLocal& in, std::vector& out) const { std::vector localJacobian(size()); localBasis.evaluateJacobian(in, localJacobian); const typename Geometry::JacobianInverseTransposed &geoJacobian = geometry.jacobianInverseTransposed(in); out.resize(size()); for(std::size_t i = 0; i < size(); ++i) geoJacobian.mv(localJacobian[i][0], out[i][0]); } }; //! Convert a local interpolation into a global interpolation /** * \tparam LocalInterpolation Type of the local interpolation to adapt. * \tparam Traits_ Traits of the corresposnding basis class. * * \implements InterpolationInterface */ template class LocalToGlobalInterpolationAdaptor { const LocalInterpolation& localInterpolation; public: typedef Traits_ Traits; //! construct a LocalToGlobalInterpolationAdaptor /** * \param localInterpolation_ The local interpolation object to adapt. * * \note This class stores the reference to the local interpolation object * passed here. Any use of this class after the reference have * become invalid results in undefined behaviour. The exception is * that the destructor of this class may still be called. */ LocalToGlobalInterpolationAdaptor ( const LocalInterpolation& localInterpolation_) : localInterpolation(localInterpolation_) { } template void interpolate(const Function& function, std::vector& out) const { localInterpolation.interpolate(function, out); } }; //! \brief Convert a simple scalar local finite element into a global finite //! element /** * The local finite elememt must be scalar, * i.e. LocalBasis::Traits::dimRange must be 1. It's values are not * transformed, but the Jacobian is (see ScalarLocalToGlobalBasisAdaptor). * * \tparam LocalFiniteElement Type of the local finite element to adapt. * \tparam Geometry Type of the local-to-global transformation. * * \implements FiniteElementInterface */ template struct ScalarLocalToGlobalFiniteElementAdaptor { /** * \implements FiniteElementInterface::Traits */ struct Traits { typedef ScalarLocalToGlobalBasisAdaptor Basis; typedef LocalToGlobalInterpolationAdaptor Interpolation; typedef typename LocalFiniteElement::Traits::LocalCoefficientsType Coefficients; }; private: const LocalFiniteElement &localFE; typename Traits::Basis basis_; typename Traits::Interpolation interpolation_; public: //! construct a ScalarLocalToGlobalFiniteElementAdaptor /** * \param localFE_ The local finite element object to adapt. * \param geometry The geometry object to use for adaption. * * \note This class stores the references passed here. Any use of this * class after these references have become invalid results in * undefined behaviour. The exception is that the destructor of * this class may still be called. */ ScalarLocalToGlobalFiniteElementAdaptor ( const LocalFiniteElement& localFE_, const Geometry &geometry) : localFE(localFE_), basis_(localFE.localBasis(), geometry), interpolation_(localFE.localInterpolation()) { } const typename Traits::Basis& basis() const { return basis_; } const typename Traits::Interpolation& interpolation() const { return interpolation_; } const typename Traits::Coefficients& coefficients() const { return localFE.localCoefficients(); } GeometryType type() const { return localFE.type(); } }; //! Factory for ScalarLocalToGlobalFiniteElementAdaptor objects /** * Constructs ScalarLocalToGlobalFiniteElementAdaptor objects given a local * finite element object and a geometry. This class is restricted to one * base variant of the local finite element. * * \tparam LocalFiniteElement Type of the local finite element to adapt. * \tparam Geometry Type of the local-to-global transformation. * * \implements FiniteElementFactoryInterface */ template class ScalarLocalToGlobalFiniteElementAdaptorFactory { const LocalFiniteElement& localFE; public: typedef ScalarLocalToGlobalFiniteElementAdaptor FiniteElement; //! construct a ScalarLocalToGlobalFiniteElementAdaptorFactory /** * \param localFE_ The local finite element object to adapt. * * \note This class stores the reference to the local finite element * object passed here. Any use of this class after this reference * has become invalid results in undefined behaviour. The exception * is that the destructor of this class may still be called. */ ScalarLocalToGlobalFiniteElementAdaptorFactory (const LocalFiniteElement &localFE_) : localFE(localFE_) {} //! construct ScalarLocalToGlobalFiniteElementAdaptor /** * \param geometry The geometry object to use for adaption. * * \note The returned object stores the reference to the geometry passed * here as well as references to internal data of this factory. Any * use of the returned value after the geometry reference or the * factory object was become invalid results in undefined behaviour. * The exception is that the destructor of the returned value may * still be called. */ const FiniteElement make(const Geometry& geometry) { return FiniteElement(localFE, geometry); } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_COMMON_LOCALTOGLOBALADAPTORS_HH dune-localfunctions-2.5.1/dune/localfunctions/common/virtualinterface.hh000066400000000000000000000356261313314431100266370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_VIRTUALINTERFACE_HH #define DUNE_VIRTUALINTERFACE_HH #include #include #include #include #include #include namespace Dune { // forward declaration needed by the helper traits template class LocalInterpolationVirtualInterface; template class LocalBasisVirtualInterface; // ----------------------------------------------------------------- // Helper traits classes // ----------------------------------------------------------------- /** * @brief Construct LocalBasisTraits with one diff order lower * * @tparam T A LocalBasisTraits class */ template struct LowerOrderLocalBasisTraits { //! The LocalBasisTraits with one order lower typedef LocalBasisTraits< typename T::DomainFieldType, T::dimDomain, typename T::DomainType, typename T::RangeFieldType, T::dimRange, typename T::RangeType, typename T::JacobianType, T::diffOrder-1> Traits; }; /** * @brief Construct LocalBasisTraits with fixed diff order * * @tparam T A LocalBasisTraits class * @tparam order The differentiation order */ template struct FixedOrderLocalBasisTraits { //! The LocalBasisTraits specified order typedef LocalBasisTraits< typename T::DomainFieldType, T::dimDomain, typename T::DomainType, typename T::RangeFieldType, T::dimRange, typename T::RangeType, typename T::JacobianType, order> Traits; }; /** * @brief Return a proper base class for functions to use with LocalInterpolation. * * @tparam FE A FiniteElement type */ template class LocalFiniteElementFunctionBase { typedef typename FE::Traits::LocalBasisType::Traits::DomainType DomainType; typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType; typedef LocalInterpolationVirtualInterface Interface; typedef typename FE::Traits::LocalInterpolationType Implementation; public: typedef VirtualFunction VirtualFunctionBase; typedef Function FunctionBase; /** \brief Base class type for functions to use with LocalInterpolation * * This is the VirtualFunction interface class if FE implements the virtual * interface and Function base class otherwise. */ typedef typename std::conditional::value, VirtualFunctionBase, FunctionBase>::type type; }; // ----------------------------------------------------------------- // Basis // ----------------------------------------------------------------- // current versions of doxygen (<= 1.6.2) enter an infinite loop when parsing // the following class #ifndef DOXYGEN /** * @brief virtual base class for a local basis * * Provides the local basis interface with pure virtual methods. * The class derives from the interface with one differentiation order lower. * * This class defines the interface using pure virtual methods. * In applications you should use the derived class * LocalBasisVirtualInterface that also * contains an evaluate with order as template parameter. * * This template method cannot be defined in the same * class as the virtual method. Otherwise name resolution fails. */ template class LocalBasisVirtualInterfaceBase : public virtual LocalBasisVirtualInterface::Traits> { typedef LocalBasisVirtualInterface::Traits> BaseInterface; public: typedef T Traits; //! \todo Please doc me! virtual void evaluate ( const typename std::template array& directions, const typename Traits::DomainType& in, std::vector& out) const = 0; using BaseInterface::evaluate; }; #endif // DOXYGEN /** * @brief virtual base class for a local basis * * Provides the local basis interface with pure virtual methods. * This is the base interface with differentiation order 0. */ template class LocalBasisVirtualInterfaceBase > { public: typedef LocalBasisTraits Traits; virtual ~LocalBasisVirtualInterfaceBase() {} //! \brief Number of shape functions virtual unsigned int size () const = 0; //! \brief Polynomial order of the shape functions virtual unsigned int order () const = 0; /** \brief Evaluate all basis function at given position * * Evaluates all shape functions at the given position and returns * these values in a vector. */ virtual void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const = 0; /** \brief Evaluate jacobian of all shape functions at given position. * * out[i][j][k] is \f$\partial_k \hat\phi_j^i \f$, when \f$\hat\phi^i \f$ is the * i'th shape function. * * \param [in] in The position where evaluated * \param [out] out The result */ virtual void evaluateJacobian(const typename Traits::DomainType& in, // position std::vector& out) const = 0; /** \brief Evaluate partial derivatives of any order of all shape functions * \param order Order of the partial derivatives, in the classic multi-index notation * \param in Position where to evaluate the derivatives * \param[out] out Return value: the desired partial derivatives */ virtual void partial(const std::array& order, const typename Traits::DomainType& in, std::vector& out) const = 0; //! \todo Please doc me! virtual void evaluate ( const typename std::template array& directions, const typename Traits::DomainType& in, std::vector& out) const = 0; }; /** * @brief virtual base class for a local basis * * Provides the local basis interface with pure virtual methods. * The class derives from the interface with one differentiation order lower. * * This class defines the interface using pure virtual methods. * It also contains the evaluate method with order as template parameter. */ template class LocalBasisVirtualInterface : public virtual LocalBasisVirtualInterfaceBase { typedef LocalBasisVirtualInterfaceBase BaseInterface; public: typedef T Traits; //! \todo Please doc me! template void evaluate ( const typename std::template array& directions, const typename Traits::DomainType& in, std::vector& out) const { typedef LocalBasisVirtualInterfaceBase::Traits > OrderKBaseInterface; const OrderKBaseInterface& asBase = *this; asBase.evaluate(directions, in, out); } using BaseInterface::size; using BaseInterface::order; using BaseInterface::partial; using BaseInterface::evaluateFunction; using BaseInterface::evaluateJacobian; /* Unfortunately, the intel compiler cannot use the different evaluate * methods with varying argument lists. :-( */ #ifndef __INTEL_COMPILER using BaseInterface::evaluate; #endif }; // ----------------------------------------------------------------- // Interpolation // ----------------------------------------------------------------- /** * @brief virtual base class for a local interpolation * * This class defines the interface using pure virtual methods. * In applications you should use the derived class * LocalInterpolationVirtualInterface that also * contains a interpolate method where the function type * is a template parameter. * * This template method cannot be defined in the same * class as the virtual method. Otherwise name resolution fails. */ template class LocalInterpolationVirtualInterfaceBase { public: //! type of virtual function to interpolate typedef Dune::VirtualFunction FunctionType; //! type of the coefficient vector in the interpolate method typedef typename RangeType::field_type CoefficientType; virtual ~LocalInterpolationVirtualInterfaceBase() {} /** \brief determine coefficients interpolating a given function * * This is the pure virtual method taking a VirtualFunction. * * \param[in] f Function instance used to interpolate. * \param[out] out Resulting coefficients vector. */ virtual void interpolate (const FunctionType& f, std::vector& out) const = 0; }; /** * @brief virtual base class for a local interpolation * * This class defines the interface using pure virtual methods. * It also contains the interpolate method with function * type as template parameter. */ template class LocalInterpolationVirtualInterface : public LocalInterpolationVirtualInterfaceBase { public: //! type of virtual function to interpolate typedef Dune::VirtualFunction FunctionType; //! type of the coefficient vector in the interpolate method typedef typename RangeType::field_type CoefficientType; virtual ~LocalInterpolationVirtualInterface() {} // This method is only notet again for to make the documentation complete. /** \brief determine coefficients interpolating a given function * * This is the pure virtual method taking a VirtualFunction. * * \param[in] f Function instance used to interpolate. * \param[out] out Resulting coefficients vector. */ virtual void interpolate (const FunctionType& f, std::vector& out) const = 0; //! \copydoc LocalInterpolationVirtualInterfaceBase::interpolate //! This uses the pure virtual method by wrapping the template argument into a VirtualFunction template void interpolate (const F& f, std::vector& out) const { const LocalInterpolationVirtualInterfaceBase& asBase = *this; asBase.interpolate(VirtualFunctionWrapper(f),out); } template void interpolate (const F& f, std::vector& out) const { std::vector outDummy; const LocalInterpolationVirtualInterfaceBase& asBase = *this; asBase.interpolate(VirtualFunctionWrapper(f),outDummy); out.resize(outDummy.size()); for(typename std::vector::size_type i=0; i struct VirtualFunctionWrapper : public FunctionType { public: VirtualFunctionWrapper(const F &f) : f_(f) {} virtual ~VirtualFunctionWrapper() {} virtual void evaluate(const DomainType& x, RangeType& y) const { f_.evaluate(x,y); } const F &f_; }; }; // ----------------------------------------------------------------- // Coefficients // ----------------------------------------------------------------- /** * @brief virtual base class for local coefficients * * This class defines the interface using pure virtual methods. */ class LocalCoefficientsVirtualInterface { public: virtual ~LocalCoefficientsVirtualInterface() {} //! number of coefficients virtual std::size_t size () const = 0; //! get i'th index const virtual LocalKey& localKey (std::size_t i) const = 0; }; // ----------------------------------------------------------------- // Finite Element // ----------------------------------------------------------------- /** * @brief virtual base class for local finite elements with functions * * This class defines the same interface using pure virtual methods. * The class derives from the interface with one differentiation order lower. */ template class LocalFiniteElementVirtualInterface : public virtual LocalFiniteElementVirtualInterface::Traits > { typedef LocalFiniteElementVirtualInterface::Traits > BaseInterface; public: typedef LocalFiniteElementTraits< LocalBasisVirtualInterface, LocalCoefficientsVirtualInterface, LocalInterpolationVirtualInterface< typename T::DomainType, typename T::RangeType> > Traits; //! \copydoc LocalFiniteElementVirtualInterface::localBasis virtual const typename Traits::LocalBasisType& localBasis () const = 0; using BaseInterface::localBasis; using BaseInterface::localCoefficients; using BaseInterface::localInterpolation; using BaseInterface::type; virtual LocalFiniteElementVirtualInterface* clone() const = 0; }; /** * @brief virtual base class for local finite elements with functions * * This class defines the same interface using pure virtual methods. * This is the base interface with differentiation order 0. */ template class LocalFiniteElementVirtualInterface > { typedef LocalBasisTraits T; public: typedef LocalFiniteElementTraits< LocalBasisVirtualInterface, LocalCoefficientsVirtualInterface, LocalInterpolationVirtualInterface< typename T::DomainType, typename T::RangeType> > Traits; virtual ~LocalFiniteElementVirtualInterface() {} //! \copydoc LocalFiniteElementVirtualInterface::localBasis virtual const typename Traits::LocalBasisType& localBasis () const = 0; //! \copydoc LocalFiniteElementVirtualInterface::localCoefficients virtual const typename Traits::LocalCoefficientsType& localCoefficients () const = 0; //! \copydoc LocalFiniteElementVirtualInterface::localInterpolation virtual const typename Traits::LocalInterpolationType& localInterpolation () const = 0; //! \copydoc LocalFiniteElementVirtualInterface::size virtual unsigned int size () const = 0; //! \copydoc LocalFiniteElementVirtualInterface::type virtual const GeometryType type () const = 0; virtual LocalFiniteElementVirtualInterface* clone() const = 0; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/common/virtualwrappers.hh000066400000000000000000000272751313314431100265430ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_VIRTUALWRAPPERS_HH #define DUNE_VIRTUALWRAPPERS_HH #include #include #include #include #include #include namespace Dune { // forward declaration needed by friend declarations template class LocalFiniteElementVirtualImp; // default clone method is the copy constructor template struct LocalFiniteElementCloneFactoryHelper { static Imp* clone(const Imp& imp) { return new Imp(imp); } }; // if FE derives from virtual interface the clone method is used template struct LocalFiniteElementCloneFactoryHelper { static Imp* clone(const Imp& imp) { return imp.clone(); } }; // factory template to clone and create an objects template struct LocalFiniteElementCloneFactory { typedef LocalFiniteElementVirtualInterface Interface; static Imp* clone(const Imp& imp) { return LocalFiniteElementCloneFactoryHelper::value>::clone(imp); } static Imp* create() { return new Imp; } }; // ----------------------------------------------------------------- // Basis // ----------------------------------------------------------------- /** * @brief class for wrapping a basis using the virtual interface * * The differentiation order of the traits T might be less than * the one in the traits of the implementation. * * @tparam T The LocalBasisTraits class * @tparam Imp LocalBasisInterface implementation */ template class LocalBasisVirtualImp : public virtual LocalBasisVirtualInterface, public LocalBasisVirtualImp::Traits,Imp> { template friend class LocalFiniteElementVirtualImp; typedef LocalBasisVirtualImp::Traits,Imp> Base; protected: //! constructor taking an implementation of the interface LocalBasisVirtualImp( const Imp &imp ) : Base(imp) {} public: typedef T Traits; using Base::size; using Base::order; using Base::evaluateFunction; using Base::evaluateJacobian; using Base::evaluate; using Base::partial; //! @copydoc LocalBasisVirtualInterface::evaluate inline void evaluate( const std::array& directions, const typename Traits::DomainType& in, std::vector& out) const { // Even for double virtualization it is save to call the template method // since the interface provides it redirecting to the virtual method // of the derived class // // Unfortunately not all compilers can determine Traits::diffOrder from // the type of the argument directions DUNE_NO_DEPRECATED_BEGIN impl_.template evaluate(directions, in, out); DUNE_NO_DEPRECATED_END } protected: using Base::impl_; }; /** * @brief class for wrapping a basis using the virtual interface * * This is the base class of all wrappers. It has differentiation order 0. * * @tparam Imp LocalBasisInterface implementation */ template class LocalBasisVirtualImp, Imp> : public virtual LocalBasisVirtualInterface > { template friend class LocalFiniteElementVirtualImp; protected: //! constructor taking an implementation of the interface LocalBasisVirtualImp( const Imp &imp ) : impl_(imp) {} public: typedef LocalBasisTraits Traits; //! @copydoc LocalBasisVirtualInterface::size unsigned int size () const { return impl_.size(); } //! @copydoc LocalBasisVirtualInterface::order unsigned int order () const { return impl_.order(); } //! @copydoc LocalBasisVirtualInterface::evaluateFunction inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { impl_.evaluateFunction(in,out); } //! @copydoc LocalBasisVirtualInterface::evaluateJacobian inline void evaluateJacobian( const typename Traits::DomainType& in, std::vector& out) const { impl_.evaluateJacobian(in,out); } /** \brief Evaluate partial derivatives of any order of all shape functions * \param order Order of the partial derivatives, in the classic multi-index notation * \param in Position where to evaluate the derivatives * \param[out] out Return value: the desired partial derivatives */ void partial(const std::array& order, const typename Traits::DomainType& in, std::vector& out) const { impl_.partial(order,in,out); } //! @copydoc LocalBasisVirtualInterface::evaluate inline void evaluate( const std::array& directions, const typename Traits::DomainType& in, std::vector& out) const { // impl_.template evaluate (directions, in,out); // impl_.template evaluate<0> (directions, in,out); impl_.evaluateFunction(in,out); } protected: const Imp& impl_; }; // ----------------------------------------------------------------- // Interpolation // ----------------------------------------------------------------- /** * @brief class for wrapping a local interpolation * using the virtual interface * * @tparam DomainType domain type of the Dune::VirtualFunction to interpolate * @tparam RangeType range type of the Dune::VirtualFunction to interpolate * \tparam Imp LocalInterpolationVirtualInterface implementation */ template class LocalInterpolationVirtualImp : public LocalInterpolationVirtualInterface< DomainType, RangeType > { template friend class LocalFiniteElementVirtualImp; typedef LocalInterpolationVirtualInterface< DomainType, RangeType > Base; protected: //! constructor taking an implementation of the Dune::LocalInterpolationVirtualInterface LocalInterpolationVirtualImp( const Imp &imp) : impl_(imp) {} public: typedef typename Base::FunctionType FunctionType; typedef typename Base::CoefficientType CoefficientType; //! \copydoc LocalInterpolationVirtualInterface::interpolate virtual void interpolate (const FunctionType& f, std::vector& out) const { impl_.interpolate(f,out); } protected: const Imp& impl_; }; // ----------------------------------------------------------------- // Coefficients // ----------------------------------------------------------------- /** * @brief class for wrapping local coefficients * using the virtual interface * * @tparam Imp LocalCoefficientsInterface implementation */ template class LocalCoefficientsVirtualImp : public LocalCoefficientsVirtualInterface { template friend class LocalFiniteElementVirtualImp; protected: //! constructor taking an implementation of the Dune::LocalCoefficientsVirtualInterface LocalCoefficientsVirtualImp( const Imp &imp ) : impl_(imp) {} public: //! @copydoc LocalCoefficientsVirtualInterface::size std::size_t size () const { return impl_.size(); } //! @copydoc LocalCoefficientsVirtualInterface::localKey const LocalKey& localKey (std::size_t i) const { return impl_.localKey(i); } protected: const Imp& impl_; }; // ----------------------------------------------------------------- // Finite Element // ----------------------------------------------------------------- /** * @brief class for wrapping a finite element using the virtual interface * * This automatically inherits the differentiation order of the wrapped * finite element and implements the corresponding interface * * @tparam Imp LocalBasisInterface implementation */ template class LocalFiniteElementVirtualImp : public virtual LocalFiniteElementVirtualInterface { typedef typename Imp::Traits::LocalBasisType::Traits T; typedef LocalFiniteElementVirtualInterface Interface; public: typedef typename Interface::Traits Traits; //! @copydoc constructor taking a LocalFiniteElementVirtualInterface implementation LocalFiniteElementVirtualImp( const Imp &imp ) : impl_(LocalFiniteElementCloneFactory::clone(imp)), localBasisImp_(impl_->localBasis()), localCoefficientsImp_(impl_->localCoefficients()), localInterpolationImp_(impl_->localInterpolation()) {} //! Default constructor. Assumes that the implementation class is default constructible as well. LocalFiniteElementVirtualImp() : impl_(LocalFiniteElementCloneFactory::create()), localBasisImp_(impl_->localBasis()), localCoefficientsImp_(impl_->localCoefficients()), localInterpolationImp_(impl_->localInterpolation()) {} //! Copy contructor needed for deep copy LocalFiniteElementVirtualImp(const LocalFiniteElementVirtualImp& other) : impl_(LocalFiniteElementCloneFactory::clone(*other.impl_)), localBasisImp_(impl_->localBasis()), localCoefficientsImp_(impl_->localCoefficients()), localInterpolationImp_(impl_->localInterpolation()) {} ~LocalFiniteElementVirtualImp() { delete impl_; } //! \copydoc LocalFiniteElementVirtualInterface::localBasis const typename Traits::LocalBasisType& localBasis () const { return localBasisImp_; } //! \copydoc LocalFiniteElementVirtualInterface::localCoefficients const typename Traits::LocalCoefficientsType& localCoefficients () const { return localCoefficientsImp_; } //! \copydoc LocalFiniteElementVirtualInterface::localInterpolation const typename Traits::LocalInterpolationType& localInterpolation () const { return localInterpolationImp_; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return impl_->size(); } //! \copydoc LocalFiniteElementVirtualInterface::type const GeometryType type () const { return impl_->type(); } /** \brief clone this wrapper * * This 'virtual copy constructor' is needed if you want to copy * the wrapper through the virtual interface. */ virtual LocalFiniteElementVirtualImp* clone() const { return new LocalFiniteElementVirtualImp(*this); } protected: const Imp* impl_; /** \todo This needs to automatically change to C0LocalBasisBla... to work with C0 shape functions */ const LocalBasisVirtualImp localBasisImp_; const LocalCoefficientsVirtualImp localCoefficientsImp_; const LocalInterpolationVirtualImp localInterpolationImp_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis.hh000066400000000000000000000005541313314431100251640ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_DUALMORTARBASIS_HH #define DUNE_LOCALFUNCTIONS_DUALMORTARBASIS_HH #include #include #endif // #ifndef DUNE_LOCALFUNCTIONS_DUALMORTARBASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/000077500000000000000000000000001313314431100246375ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/CMakeLists.txt000066400000000000000000000003231313314431100273750ustar00rootroot00000000000000add_subdirectory(dualp1) add_subdirectory(dualq1) add_subdirectory(test) install(FILES dualp1.hh dualq1.hh dualpq1factory.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/dualmortarbasis) dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualp1.hh000066400000000000000000000046511313314431100263540ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DUAL_P1LOCALFINITEELEMENT_HH #define DUNE_DUAL_P1LOCALFINITEELEMENT_HH #include #include #include "dualp1/dualp1localbasis.hh" #include "dualp1/dualp1localcoefficients.hh" #include "dualp1/dualp1localinterpolation.hh" namespace Dune { /** * \brief The local dual p1 finite element on simplices * * Note that if the dual functions are chosen to be dual on the faces, * the integrated product of a Lagrange \f$\lambda_p\f$ and dual * function \f$\theta_q\f$ over faces not containing \f$q\f$ does in * general not vanish. * * \ingroup DualMortar * * \tparam D Domain data type * \tparam R Range data type * \tparam dim Dimension of the simplex * \tparam faceDual If set, the basis functions are bi-orthogonal only on faces containing the corresponding vertex. */ template class DualP1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits,DualP1LocalCoefficients, DualP1LocalInterpolation > > Traits; /** \todo Please doc me ! */ DualP1LocalFiniteElement () { gt.makeSimplex(dim); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } DualP1LocalFiniteElement* clone () const { return new DualP1LocalFiniteElement(*this); } private: DualP1LocalBasis basis; DualP1LocalCoefficients coefficients; DualP1LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualp1/000077500000000000000000000000001313314431100260255ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualp1/CMakeLists.txt000066400000000000000000000002651313314431100305700ustar00rootroot00000000000000install(FILES dualp1localbasis.hh dualp1localcoefficients.hh dualp1localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/dualmortarbasis/dualp1) dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualp1/dualp1localbasis.hh000066400000000000000000000075261313314431100316030ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DUAL_P1_LOCALBASIS_HH #define DUNE_DUAL_P1_LOCALBASIS_HH #include #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Dual Lagrange shape functions on the simplex. Defines the linear dual shape functions on the simplex. Note that if the dual functions are chosen to be dual on the faces, the integrated product of a Lagrange \f$\lambda_p\f$ and dual function \f$\theta_q\f$ over faces not containing \f$q\f$ does in general not vanish. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam dim The dimension of the simplex \tparam faceDual If set, the basis functions are bi-orthogonal only on faces containing the corresponding vertex. \nosubgrouping */ template class DualP1LocalBasis { public: //! Determines if the basis is only biorthogonal on adjacent faces static const bool faceDual = faceDualT; //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return dim+1; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { // evaluate P1 basis functions std::vector p1Values(size()); p1Values[0] = 1.0; for (int i=0; i& out) const { // evaluate P1 jacobians std::vector p1Jacs(size()); for (int i=0; i& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 1; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualp1/dualp1localcoefficients.hh000066400000000000000000000016341313314431100331350ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DUAL_P1_LOCALCOEFFICIENTS_HH #define DUNE_DUAL_P1_LOCALCOEFFICIENTS_HH #include #include #include namespace Dune { /** \brief Local coefficients for dual simplex P1 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class DualP1LocalCoefficients { public: //! \brief Standard constructor DualP1LocalCoefficients () : li(size()) { for (std::size_t i=0; i li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualp1/dualp1localinterpolation.hh000066400000000000000000000026571313314431100333710ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DUAL_P1_LOCALINTERPOLATION_HH #define DUNE_DUAL_P1_LOCALINTERPOLATION_HH #include namespace Dune { template class DualP1LocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; typename LB::Traits::DomainType x; // If the dual functions are dual on the faces, // then adjust the interpolation weights const int faceDual(LB::faceDual); // compute P1 interpolation coefficients std::vector p1Interpolation(dim+1); // vertex 0 for (int i=0; i #include #include #include namespace Dune { template class DualPQ1LocalFiniteElementCache { protected: typedef Dune::DualP1LocalFiniteElement DualP1; typedef Dune::DualQ1LocalFiniteElement DualQ1; typedef typename Dune::FixedOrderLocalBasisTraits::Traits T; typedef Dune::LocalFiniteElementVirtualInterface FE; typedef std::map FEMap; public: /** \brief Type of the finite elements stored in this cache */ typedef FE FiniteElementType; ~DualPQ1LocalFiniteElementCache() { typename FEMap::iterator it = cache_.begin(); typename FEMap::iterator end = cache_.end(); for(; it!=end; ++it) delete it->second; } //! create finite element for given GeometryType static FE* create(const Dune::GeometryType& gt) { if (gt.isSimplex()) return new Dune::LocalFiniteElementVirtualImp(DualP1()); if (gt.isCube()) return new Dune::LocalFiniteElementVirtualImp(DualQ1()); return 0; } //! Get local finite element for given GeometryType const FiniteElementType& get(const Dune::GeometryType& gt) const { typename FEMap::const_iterator it = cache_.find(gt); if (it==cache_.end()) { FiniteElementType* fe = create(gt); if (fe==0) DUNE_THROW(Dune::NotImplemented,"No Dual P/Q1 like local finite element available for geometry type " << gt); cache_[gt] = fe; return *fe; } return *(it->second); } protected: mutable FEMap cache_; }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_DUAL_P1_Q1_FACTORY_HH dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualq1.hh000066400000000000000000000156561313314431100263640ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DUAL_Q1_LOCALFINITEELEMENT_HH #define DUNE_DUAL_Q1_LOCALFINITEELEMENT_HH #include #include #include #include #include #include #include #include #include "dualq1/dualq1localbasis.hh" #include "dualq1/dualq1localcoefficients.hh" #include "dualq1/dualq1localinterpolation.hh" namespace Dune { /** * \brief The local dual Q1 finite element on cubes * * Note that if the dual functions are chosen to be dual on the faces, * the integrated product of a Lagrange \f$\lambda_p\f$ and dual * function \f$\theta_q\f$ over faces not containing \f$q\f$ does in * general not vanish. * * \ingroup DualMortar * * \tparam D Domain data type * \tparam R Range data type * \tparam dim Dimension of the hypercube * \tparam faceDual If set, the basis functions are bi-orthogonal only on faces containing the corresponding vertex. */ template class DualQ1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits,DualQ1LocalCoefficients, DualQ1LocalInterpolation > > Traits; /** \todo Please doc me ! */ DualQ1LocalFiniteElement () { gt.makeCube(dim); if (faceDual) setupFaceDualCoefficients(); else setupDualCoefficients(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } DualQ1LocalFiniteElement* clone () const { return new DualQ1LocalFiniteElement(*this); } private: /** \brief Setup the coefficients for the face dual basis functions. */ void setupFaceDualCoefficients(); /** \brief Setup the coefficients for the dual basis functions. */ void setupDualCoefficients(); DualQ1LocalBasis basis; DualQ1LocalCoefficients coefficients; DualQ1LocalInterpolation > interpolation; GeometryType gt; }; template void DualQ1LocalFiniteElement::setupDualCoefficients() { const int size = 1 <, size> coeffs; // dual basis functions are linear combinations of Lagrange elements // compute these coefficients here because the basis and the local interpolation needs them const auto& quad = Dune::QuadratureRules::rule(gt, 2*dim); // assemble mass matrix on the reference element Dune::FieldMatrix massMat; massMat = 0; // and the integrals of the lagrange shape functions std::vector > integral(size); for (int i=0; i q1Basis; for(size_t pt=0; pt& pos = quad[pt].position(); std::vector > q1Values(size); q1Basis.evaluateFunction(pos,q1Values); D weight = quad[pt].weight(); for (int k=0; k rhs(0); rhs[i] = integral[i]; coeffs[i] = 0; massMat.solve(coeffs[i] ,rhs); } basis.setCoefficients(coeffs); interpolation.setCoefficients(coeffs); } template void DualQ1LocalFiniteElement::setupFaceDualCoefficients() { const int size = 1 <, size> coeffs; // dual basis functions are linear combinations of Lagrange elements Dune::Q1LocalBasis q1Basis; const auto& refElement = Dune::ReferenceElements::general(gt); // loop over faces for (size_t i=0; i::rule(refElement.type(i,1),2*dim); // for each face assemble the mass matrix over the face of all // non-vanishing basis functions, // for cubes refElement.size(i,1,dim)=size/2 Dune::FieldMatrix massMat; massMat = 0; // get geometry const auto& geometry = refElement.template geometry<1>(i); // and the integrals of the lagrange shape functions std::vector > integral(size/2); for (int k=0; k > q1Values(size); q1Basis.evaluateFunction(elementPos,q1Values); D weight = quad[pt].weight(); for (int k=0; k rhs(0); rhs[l] = integral[l]; Dune::FieldVector x(0); massMat.solve(x ,rhs); for (int k=0; k #include #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Dual Lagrange shape functions of order 1 on the reference cube. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam dim Dimension of the cube \nosubgrouping */ template class DualQ1LocalBasis { public: typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; void setCoefficients(const std::array ,(1<& coefficients) { coefficients_ = coefficients; } //! \brief number of shape functions unsigned int size () const { return 1<& out) const { // compute q1 values std::vector q1Values(size()); for (size_t i=0; i& out) const // return value { // compute q1 jacobians std::vector q1Jacs(size()); // Loop over all shape functions for (size_t i=0; i& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 1; } private: std::array ,(1< coefficients_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualq1/dualq1localcoefficients.hh000066400000000000000000000017221313314431100331350ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DUAL_Q1_LOCALCOEFFICIENTS_HH #define DUNE_DUAL_Q1_LOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for dual Q1 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class DualQ1LocalCoefficients { public: //! \brief Standard constructor DualQ1LocalCoefficients () : li(1< li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/dualq1/dualq1localinterpolation.hh000066400000000000000000000036421313314431100333660ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DUAL_Q1_LOCALINTERPOLATION_HH #define DUNE_DUAL_Q1_LOCALINTERPOLATION_HH #include #include #include #include namespace Dune { /** \todo Please doc me! */ template class DualQ1LocalInterpolation { public: void setCoefficients(const std::array ,(1<& coefficients) { coefficients_ = coefficients; } //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; const int size = 1< q1Coefficients; for (int i=0; i< (1< mat; for (int i=0; i sol(0); mat.solve(sol,q1Coefficients); // write result in out vector for (int i=0; i ,(1< coefficients_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/test/000077500000000000000000000000001313314431100256165ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/test/CMakeLists.txt000066400000000000000000000000571313314431100303600ustar00rootroot00000000000000dune_add_test(SOURCES test-biorthogonality.cc) dune-localfunctions-2.5.1/dune/localfunctions/dualmortarbasis/test/test-biorthogonality.cc000066400000000000000000000212521313314431100323210ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "config.h" #include #include #include #include #include #include #include #include #include double TOL = 1e-9; //! \brief Test if dual and Lagrange functions are bi-orthogonal, i.e. \integral dual_i * lagrange_j = \delta_ij \integral lagrange_j template bool testBiorthogonality(const DualLfe& dualLfe, const LagrangeLfe& lagrangeLfe) { const int dim = DualLfe::Traits::LocalBasisType::Traits::dimDomain; const Dune::QuadratureRule& quad = Dune::QuadratureRules::rule(dualLfe.type(),dualLfe.localBasis().order() + lagrangeLfe.localBasis().order()); const unsigned int numLagBasFct = lagrangeLfe.localBasis().size(); const unsigned int numDualBasFct = dualLfe.localBasis().size(); // save the integrals of all mixed combinations in mixedMassMat[numLagBasFct][numDualBasFct] std::vector > mixedMassMat(numLagBasFct); for (unsigned int i = 0; i < numLagBasFct; i++) mixedMassMat[i].resize(numDualBasFct); // integrate all lagrange basis functions std::vector integralLagrange(numLagBasFct); for (unsigned int k=0; k& pos = quad[i].position(); std::vector dualValues(dualLfe.localBasis().size()); std::vector lagrangeValues(lagrangeLfe.localBasis().size()); // evaluate basis functions dualLfe.localBasis().evaluateFunction(pos,dualValues); lagrangeLfe.localBasis().evaluateFunction(pos,lagrangeValues); // check if the values sum up to one double unity = 0; for (unsigned int l=0; l TOL) std::cout<<"Dual basis functions don't sum up to 1\n"; double weight = quad[i].weight(); for (unsigned int k=0; k TOL) { std::cout<<"Dual basis function "< bool testFaceBiorthogonality(const DualLfe& dualLfe, const LagrangeLfe& lagrangeLfe) { using DualTraits = typename DualLfe::Traits::LocalBasisType::Traits; using LagrangeTraits = typename LagrangeLfe::Traits::LocalBasisType::Traits; const int dim = DualTraits::dimDomain; assert (dim == LagrangeTraits::dimDomain); using ctype = typename DualTraits::DomainFieldType; using field_type = typename DualTraits::RangeFieldType; const auto& refElement = Dune::ReferenceElements::general(dualLfe.type()); const unsigned int numLagBasFct = lagrangeLfe.localBasis().size(); const unsigned int numDualBasFct = dualLfe.localBasis().size(); // save the integrals of all mixed combinations std::vector > mixedMassMat(numLagBasFct); for (unsigned int i = 0; i < numLagBasFct; i++) mixedMassMat[i].resize(numDualBasFct); // integrate all lagrange basis functions std::vector integralLagrange(numLagBasFct); std::vector dualValues(dualLfe.localBasis().size()); std::vector lagrangeValues(lagrangeLfe.localBasis().size()); bool biorthog = true; // loop over the number of faces for (int i=0; i(i); // get a quadrature rule const auto& quad = Dune::QuadratureRules::rule(refElement.type(i,1), dualLfe.localBasis().order() + lagrangeLfe.localBasis().order()); // initialise with zeroes for (unsigned int k=0; k TOL) { std::cout<<"for face "< dualP1lfem1D; Dune::P1LocalFiniteElement p1lfem1D; success = testBiorthogonality(dualP1lfem1D,p1lfem1D) and success; Dune::DualP1LocalFiniteElement dualP1lfem2D; Dune::P1LocalFiniteElement p1lfem2D; success = testBiorthogonality(dualP1lfem2D,p1lfem2D) and success; Dune::DualP1LocalFiniteElement dualP1lfem3D; Dune::P1LocalFiniteElement p1lfem3D; success = testBiorthogonality(dualP1lfem3D,p1lfem3D) and success; Dune::DualQ1LocalFiniteElement dualQ1lfem1D; Dune::Q1LocalFiniteElement q1lfem1D; success = testBiorthogonality(dualQ1lfem1D,q1lfem1D) and success; Dune::DualQ1LocalFiniteElement dualQ1lfem2D; Dune::Q1LocalFiniteElement q1lfem2D; success = testBiorthogonality(dualQ1lfem2D,q1lfem2D) and success; Dune::DualQ1LocalFiniteElement dualQ1lfem3D; Dune::Q1LocalFiniteElement q1lfem3D; success = testBiorthogonality(dualQ1lfem3D,q1lfem3D) and success; Dune::DualP1LocalFiniteElement dualFaceP1lfem1D; success = testFaceBiorthogonality(dualFaceP1lfem1D,p1lfem1D) and success; Dune::DualP1LocalFiniteElement dualFaceP1lfem2D; success = testFaceBiorthogonality(dualFaceP1lfem2D,p1lfem2D) and success; Dune::DualP1LocalFiniteElement dualFaceP1lfem3D; success = testFaceBiorthogonality(dualFaceP1lfem3D,p1lfem3D) and success; Dune::DualQ1LocalFiniteElement dualFaceQ1lfem1D; success = testFaceBiorthogonality(dualFaceQ1lfem1D,q1lfem1D) and success; Dune::DualQ1LocalFiniteElement dualFaceQ1lfem2D; success = testFaceBiorthogonality(dualFaceQ1lfem2D,q1lfem2D) and success; Dune::DualQ1LocalFiniteElement dualFaceQ1lfem3D; success = testFaceBiorthogonality(dualFaceQ1lfem3D,q1lfem3D) and success; return success ? 0 : 1; } catch(Dune::Exception e) { std::cout< #include #include #include "hierarchicalp2/hierarchicalsimplexp2localbasis.hh" #include "hierarchicalp2/hierarchicalsimplexp2localinterpolation.hh" namespace Dune { /** \todo Please doc me ! */ template class HierarchicalP2LocalFiniteElement { static_assert(1 <= dim && dim <= 3, "HierarchicalP2LocalFiniteElement only implemented for dim==1, 2, 3."); public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits< HierarchicalSimplexP2LocalBasis, typename PkLocalFiniteElement::Traits::LocalCoefficientsType, HierarchicalSimplexP2LocalInterpolation > > Traits; /** \todo Please doc me ! */ HierarchicalP2LocalFiniteElement () { gt.makeSimplex(dim); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } HierarchicalP2LocalFiniteElement* clone () const { return new HierarchicalP2LocalFiniteElement(*this); } private: HierarchicalSimplexP2LocalBasis basis; typename Traits::LocalCoefficientsType coefficients; HierarchicalSimplexP2LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalp2/000077500000000000000000000000001313314431100267415ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalp2/CMakeLists.txt000066400000000000000000000002731313314431100315030ustar00rootroot00000000000000install(FILES hierarchicalsimplexp2localbasis.hh hierarchicalsimplexp2localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/hierarchical/hierarchicalp2) hierarchicalsimplexp2localbasis.hh000066400000000000000000000265241313314431100355330ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalp2// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_HIERARCHICAL_SIMPLEX_P2_LOCALBASIS_HH #define DUNE_HIERARCHICAL_SIMPLEX_P2_LOCALBASIS_HH /** \file \brief Hierarchical p2 shape functions for the simplex */ #include #include #include #include namespace Dune { template class HierarchicalSimplexP2LocalBasis { public: HierarchicalSimplexP2LocalBasis() { DUNE_THROW(Dune::NotImplemented,"HierarchicalSimplexP2LocalBasis not implemented for dim > 3."); } }; /**@ingroup LocalBasisImplementation \brief Hierarchical P2 basis in 1d. The shape functions are associated to the following points: - \f$ f_0 \f$ ~ (0.0) // linear function - \f$ f_1 \f$ ~ (1.0) // linear function - \f$ f_2 \f$ ~ (0.5) // quadratic bubble \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class HierarchicalSimplexP2LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 3; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(3); out[0] = 1-in[0]; out[1] = 1-4*(in[0]-0.5)*(in[0]-0.5); out[2] = in[0]; } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(3); out[0][0][0] = -1; out[1][0][0] = 4-8*in[0]; out[2][0][0] = 1; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = order[0]; if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); out[0] = -1; out[1] = 4-8*in[0]; out[2] = 1; } else if (totalOrder == 2) { out.resize(size()); out[0] = 0; out[1] = -8; out[2] = 0; } else { out.resize(size()); out[0] = out[1] = out[2] = 0; } } /** \brief Polynomial order of the shape functions (2, in this case) */ unsigned int order () const { return 2; } }; /**@ingroup LocalBasisImplementation \brief Hierarchical P2 basis in 2d. The shape functions are associated to the following points: The functions are associated to points by: - \f$ f_0 \f$ ~ (0.0, 0.0) - \f$ f_1 \f$ ~ (0.5, 0.0) - \f$ f_2 \f$ ~ (1.0, 0.0) - \f$ f_3 \f$ ~ (0.0, 0.5) - \f$ f_4 \f$ ~ (0.5, 0.5) - \f$ f_5 \f$ ~ (0.0, 1.0) \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class HierarchicalSimplexP2LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 6; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(6); out[0] = 1 - in[0] - in[1]; out[1] = 4*in[0]*(1-in[0]-in[1]); out[2] = in[0]; out[3] = 4*in[1]*(1-in[0]-in[1]); out[4] = 4*in[0]*in[1]; out[5] = in[1]; } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(6); out[0][0][0] = -1; out[0][0][1] = -1; out[1][0][0] = 4-8*in[0]-4*in[1]; out[1][0][1] = -4*in[0]; out[2][0][0] = 1; out[2][0][1] = 0; out[3][0][0] = -4*in[1]; out[3][0][1] = 4-4*in[0]-8*in[1]; out[4][0][0] = 4*in[1]; out[4][0][1] = 4*in[0]; out[5][0][0] = 0; out[5][0][1] = 1; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0] = -1; out[1] = 4-8*in[0]-4*in[1]; out[2] = 1; out[3] = -4*in[1]; out[4] = 4*in[1]; out[5] = 0; break; case 1: out[0] = -1; out[1] = -4*in[0]; out[2] = 0; out[3] = 4-4*in[0]-8*in[1]; out[4] = 4*in[0]; out[5] = 1; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } /** \brief Polynomial order of the shape functions (2 in this case) */ unsigned int order () const { return 2; } }; /**@ingroup LocalBasisImplementation \brief Hierarchical P2 basis in 3d. The shape functions are associated to the following points: The functions are associated to points by: - \f$ f_0 \f$ ~ (0.0, 0.0, 0.0) - \f$ f_1 \f$ ~ (0.5, 0.0, 0.0) - \f$ f_2 \f$ ~ (1.0, 0.0, 0.0) - \f$ f_3 \f$ ~ (0.0, 0.5, 0.0) - \f$ f_4 \f$ ~ (0.5, 0.5, 0.0) - \f$ f_5 \f$ ~ (0.0, 1.0, 0.0) - \f$ f_6 \f$ ~ (0.0, 0.0, 0.5) - \f$ f_7 \f$ ~ (0.5, 0.0, 0.5) - \f$ f_8 \f$ ~ (0.0, 0.5, 0.5) - \f$ f_9 \f$ ~ (0.0, 0.0, 1.0) \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class HierarchicalSimplexP2LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 10; } //! \brief Evaluate all shape functions void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(10); out[0] = 1 - in[0] - in[1] - in[2]; out[1] = 4 * in[0] * (1 - in[0] - in[1] - in[2]); out[2] = in[0]; out[3] = 4 * in[1] * (1 - in[0] - in[1] - in[2]); out[4] = 4 * in[0] * in[1]; out[5] = in[1]; out[6] = 4 * in[2] * (1 - in[0] - in[1] - in[2]); out[7] = 4 * in[0] * in[2]; out[8] = 4 * in[1] * in[2]; out[9] = in[2]; } //! \brief Evaluate Jacobian of all shape functions void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(10); out[0][0][0] = -1; out[0][0][1] = -1; out[0][0][2] = -1; out[1][0][0] = 4-8*in[0]-4*in[1]-4*in[2]; out[1][0][1] = -4*in[0]; out[1][0][2] = -4*in[0]; out[2][0][0] = 1; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = -4*in[1]; out[3][0][1] = 4-4*in[0]-8*in[1]-4*in[2]; out[3][0][2] = -4*in[1]; out[4][0][0] = 4*in[1]; out[4][0][1] = 4*in[0]; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 1; out[5][0][2] = 0; out[6][0][0] = -4*in[2]; out[6][0][1] = -4*in[2]; out[6][0][2] = 4-4*in[0]-4*in[1]-8*in[2]; out[7][0][0] = 4*in[2]; out[7][0][1] = 0; out[7][0][2] = 4*in[0]; out[8][0][0] = 0; out[8][0][1] = 4*in[2]; out[8][0][2] = 4*in[1]; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 1; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0] = -1; out[1] = 4-8*in[0]-4*in[1]-4*in[2]; out[2] = 1; out[3] = -4*in[1]; out[4] = 4*in[1]; out[5] = 0; out[6] = -4*in[2]; out[7] = 4*in[2]; out[8] = 0; out[9] = 0; break; case 1: out[0] = -1; out[1] = -4*in[0]; out[2] = 0; out[3] = 4-4*in[0]-8*in[1]-4*in[2]; out[4] = 4*in[0]; out[5] = 1; out[6] = -4*in[2]; out[7] = 0; out[8] = 4*in[2]; out[9] = 0; break; case 2: out[0] = -1; out[1] = -4*in[0]; out[2] = 0; out[3] = -4*in[1]; out[4] = 0; out[5] = 0; out[6] = 4-4*in[0]-4*in[1]-8*in[2]; out[7] = 4*in[0]; out[8] = 4*in[1]; out[9] = 1; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } /** \brief Polynomial order of the shape functions (2 in this case) */ unsigned int order () const { return 2; } }; } #endif hierarchicalsimplexp2localinterpolation.hh000066400000000000000000000057121313314431100373150ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalp2// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_HIERARCHICAL_SIMPLEX_P2_LOCALINTERPOLATION_HH #define DUNE_HIERARCHICAL_SIMPLEX_P2_LOCALINTERPOLATION_HH #include namespace Dune { /** \tparam LB The LocalBasis implementation */ template class HierarchicalSimplexP2LocalInterpolation { public: template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; static_assert(LB::Traits::dimDomain <= 3, "LocalInterpolation for HierarchicalSimplexP2 finite elements" " is only implemented for dimDomain <=3!"); switch ( int(LB::Traits::dimDomain)) { case 1 : out.resize(3); // First: the two vertex dofs x[0] = 0.0; f.evaluate(x, y); out[0] = y; x[0] = 1.0; f.evaluate(x, y); out[2] = y; // Then: the edge dof x[0] = 0.5; f.evaluate(x, y); out[1] = y - 0.5*(out[0] + out[2]); break; case 2 : out.resize(6); // First: the three vertex dofs x[0] = 0.0; x[1] = 0.0; f.evaluate(x, y); out[0] = y; x[0] = 1.0; x[1] = 0.0; f.evaluate(x, y); out[2] = y; x[0] = 0.0; x[1] = 1.0; f.evaluate(x, y); out[5] = y; // Then: the three edge dofs x[0] = 0.5; x[1] = 0.0; f.evaluate(x, y); out[1] = y - 0.5*(out[0] + out[2]); x[0] = 0.0; x[1] = 0.5; f.evaluate(x, y); out[3] = y - 0.5*(out[0] + out[5]); x[0] = 0.5; x[1] = 0.5; f.evaluate(x, y); out[4] = y - 0.5*(out[2] + out[5]); break; case 3 : out.resize(10); // First: the four vertex dofs x[0] = 0.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x, y); out[0] = y; x[0] = 1.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x, y); out[2] = y; x[0] = 0.0; x[1] = 1.0; x[2] = 0.0; f.evaluate(x, y); out[5] = y; x[0] = 0.0; x[1] = 0.0; x[2] = 1.0; f.evaluate(x, y); out[9] = y; // Then: the six edge dofs x[0] = 0.5; x[1] = 0.0; x[2] = 0.0; f.evaluate(x, y); out[1] = y - 0.5*(out[0] + out[2]); x[0] = 0.0; x[1] = 0.5; x[2] = 0.0; f.evaluate(x, y); out[3] = y - 0.5*(out[0] + out[5]); x[0] = 0.5; x[1] = 0.5; x[2] = 0.0; f.evaluate(x, y); out[4] = y - 0.5*(out[2] + out[5]); x[0] = 0.0; x[1] = 0.0; x[2] = 0.5; f.evaluate(x, y); out[6] = y - 0.5*(out[0] + out[9]); x[0] = 0.5; x[1] = 0.0; x[2] = 0.5; f.evaluate(x, y); out[7] = y - 0.5*(out[2] + out[9]); x[0] = 0.0; x[1] = 0.5; x[2] = 0.5; f.evaluate(x, y); out[8] = y - 0.5*(out[5] + out[9]); break; } } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalp2withelementbubble.hh000066400000000000000000000045271313314431100327140ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_HIERARCHICAL_P2_WITH_ELEMENTBUBBLE_LOCALFINITEELEMENT_HH #define DUNE_HIERARCHICAL_P2_WITH_ELEMENTBUBBLE_LOCALFINITEELEMENT_HH #include #include #include namespace Dune { /** \todo Please doc me ! */ template class HierarchicalP2WithElementBubbleLocalFiniteElement { static_assert(dim==2, "HierarchicalP2WithElementBubbleLocalFiniteElement only implemented for dim==2."); public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, HierarchicalSimplexP2WithElementBubbleLocalCoefficients, HierarchicalSimplexP2WithElementBubbleLocalInterpolation > > Traits; /** \todo Please doc me ! */ HierarchicalP2WithElementBubbleLocalFiniteElement () { gt_.makeTriangle(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis_.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt_; } HierarchicalP2WithElementBubbleLocalFiniteElement* clone () const { return new HierarchicalP2WithElementBubbleLocalFiniteElement(*this); } private: HierarchicalSimplexP2WithElementBubbleLocalBasis basis_; HierarchicalSimplexP2WithElementBubbleLocalCoefficients coefficients_; HierarchicalSimplexP2WithElementBubbleLocalInterpolation > interpolation_; GeometryType gt_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalp2withelementbubble/000077500000000000000000000000001313314431100323635ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000002461313314431100350460ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalp2withelementbubbleinstall(FILES hierarchicalsimplexp2withelementbubble.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/hierarchical/hierarchicalp2withelementbubble) hierarchicalsimplexp2withelementbubble.hh000066400000000000000000000365411313314431100425420ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalp2withelementbubble// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_HIERARCHICAL_SIMPLEX_P2_WITH_ELEMENT_BUBBLE_LOCALBASIS_HH #define DUNE_HIERARCHICAL_SIMPLEX_P2_WITH_ELEMENT_BUBBLE_LOCALBASIS_HH /** \file \brief Hierarchical p2 shape functions for the simplex */ #include #include #include #include #include #include namespace Dune { template class HierarchicalSimplexP2WithElementBubbleLocalBasis { public: HierarchicalSimplexP2WithElementBubbleLocalBasis() { DUNE_THROW(Dune::NotImplemented,"HierarchicalSimplexP2LocalBasis not implemented for dim > 3."); } }; /**@ingroup LocalBasisImplementation \brief Hierarchical P2 basis in 1d. The shape functions are associated to the following points: f_0 ~ (0.0) // linear function f_1 ~ (1.0) // linear function f_2 ~ (0.5) // quadratic bubble \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class HierarchicalSimplexP2WithElementBubbleLocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 3; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(3); out[0] = 1-in[0]; out[1] = in[0]; out[2] = 1-4*(in[0]-0.5)*(in[0]-0.5); } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(3); out[0][0][0] = -1; out[1][0][0] = 1; out[2][0][0] = 4-8*in[0]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = order[0]; if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); out[0] = -1; out[1] = 1; out[2] = 4-8*in[0]; } else if (totalOrder == 2) { out.resize(size()); out[0] = 0; out[1] = 0; out[2] =-8; } else { out.resize(size()); out[0] = out[1] = out[2] = 0; } } /** \brief Polynomial order of the shape functions (2, in this case) */ unsigned int order () const { return 2; } }; /**@ingroup LocalBasisImplementation \brief Hierarchical P2 basis in 1d. The shape functions are associated to the following points: The functions are associated to points by: f_0 ~ (0.0, 0.0) f_1 ~ (0.5, 0.0) f_2 ~ (1.0, 0.0) f_3 ~ (0.0, 0.5) f_4 ~ (0.5, 0.5) f_5 ~ (0.0, 1.0) f_6 ~ (1/3, 1/3) \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class HierarchicalSimplexP2WithElementBubbleLocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 7; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(7); out[0] = 1 - in[0] - in[1]; out[1] = 4*in[0]*(1-in[0]-in[1]); out[2] = in[0]; out[3] = 4*in[1]*(1-in[0]-in[1]); out[4] = 4*in[0]*in[1]; out[5] = in[1]; out[6] = 27*in[0]*in[1]*(1-in[0]-in[1]); } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(7); out[0][0][0] = -1; out[0][0][1] = -1; out[1][0][0] = 4-8*in[0]-4*in[1]; out[1][0][1] = -4*in[0]; out[2][0][0] = 1; out[2][0][1] = 0; out[3][0][0] = -4*in[1]; out[3][0][1] = 4-4*in[0]-8*in[1]; out[4][0][0] = 4*in[1]; out[4][0][1] = 4*in[0]; out[5][0][0] = 0; out[5][0][1] = 1; // Cubic bubble out[6][0][0] = 27 * in[1] * (1 - 2*in[0] - in[1]); out[6][0][1] = 27 * in[0] * (1 - 2*in[1] - in[0]); } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0] = -1; out[1] = 4-8*in[0]-4*in[1]; out[2] = 1; out[3] = -4*in[1]; out[4] = 4*in[1]; out[5] = 0; out[6] = 27 * in[1] * (1 - 2*in[0] - in[1]); break; case 1: out[0] = -1; out[1] = -4*in[0]; out[2] = 0; out[3] = 4-4*in[0]-8*in[1]; out[4] = 4*in[0]; out[5] = 1; out[6] = 27 * in[0] * (1 - 2*in[1] - in[0]); break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } /** \brief Polynomial order of the shape functions (3 in this case) */ unsigned int order () const { return 3; } }; /**@ingroup LocalBasisImplementation \brief Hierarchical P2 basis in 1d. The shape functions are associated to the following points: The functions are associated to points by: f_0 ~ (0.0, 0.0, 0.0) f_1 ~ (0.5, 0.0, 0.0) f_2 ~ (1.0, 0.0, 0.0) f_3 ~ (0.0, 0.5, 0.0) f_4 ~ (0.5, 0.5, 0.0) f_5 ~ (0.0, 1.0, 0.0) f_6 ~ (0.0, 0.0, 0.5) f_7 ~ (0.5, 0.0, 0.5) f_8 ~ (0.0, 0.5, 0.5) f_9 ~ (0.0, 0.0, 1.0) f_10 ~ (1/3, 1/3, 1/3) \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class HierarchicalSimplexP2WithElementBubbleLocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 11; } //! \brief Evaluate all shape functions void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(10); out[0] = 1 - in[0] - in[1] - in[2]; out[1] = 4 * in[0] * (1 - in[0] - in[1] - in[2]); out[2] = in[0]; out[3] = 4 * in[1] * (1 - in[0] - in[1] - in[2]); out[4] = 4 * in[0] * in[1]; out[5] = in[1]; out[6] = 4 * in[2] * (1 - in[0] - in[1] - in[2]); out[7] = 4 * in[0] * in[2]; out[8] = 4 * in[1] * in[2]; out[9] = in[2]; // quartic element bubble out[10] = 81*in[0]*in[1]*in[2]*(1-in[0]-in[1]-in[2]); } //! \brief Evaluate Jacobian of all shape functions void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(10); out[0][0][0] = -1; out[0][0][1] = -1; out[0][0][2] = -1; out[1][0][0] = 4-8*in[0]-4*in[1]-4*in[2]; out[1][0][1] = -4*in[0]; out[1][0][2] = -4*in[0]; out[2][0][0] = 1; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = -4*in[1]; out[3][0][1] = 4-4*in[0]-8*in[1]-4*in[2]; out[3][0][2] = -4*in[1]; out[4][0][0] = 4*in[1]; out[4][0][1] = 4*in[0]; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 1; out[5][0][2] = 0; out[6][0][0] = -4*in[2]; out[6][0][1] = -4*in[2]; out[6][0][2] = 4-4*in[0]-4*in[1]-8*in[2]; out[7][0][0] = 4*in[2]; out[7][0][1] = 0; out[7][0][2] = 4*in[0]; out[8][0][0] = 0; out[8][0][1] = 4*in[2]; out[8][0][2] = 4*in[1]; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 1; out[10][0][0] = 81 * in[1] * in[2] * (1 - 2*in[0] - in[1] - in[2]); out[10][0][1] = 81 * in[0] * in[2] * (1 - in[0] - 2*in[1] - in[2]); out[10][0][2] = 81 * in[0] * in[1] * (1 - in[0] - in[1] - 2*in[2]); } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0] = -1; out[1] = 4-8*in[0]-4*in[1]-4*in[2]; out[2] = 1; out[3] = -4*in[1]; out[4] = 4*in[1]; out[5] = 0; out[6] = -4*in[2]; out[7] = 4*in[2]; out[8] = 0; out[9] = 0; out[10] = 81 * in[1] * in[2] * (1 - 2*in[0] - in[1] - in[2]); break; case 1: out[0] = -1; out[1] = -4*in[0]; out[2] = 0; out[3] = 4-4*in[0]-8*in[1]-4*in[2]; out[4] = 4*in[0]; out[5] = 1; out[6] = -4*in[2]; out[7] = 0; out[8] = 4*in[2]; out[9] = 0; out[10] = 81 * in[0] * in[2] * (1 - in[0] - 2*in[1] - in[2]); break; case 2: out[0] = -1; out[1] = -4*in[0]; out[2] = 0; out[3] = -4*in[1]; out[4] = 0; out[5] = 0; out[6] = 4-4*in[0]-4*in[1]-8*in[2]; out[7] = 4*in[0]; out[8] = 4*in[1]; out[9] = 1; out[10] = 81 * in[0] * in[1] * (1 - in[0] - in[1] - 2*in[2]); break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } /** \brief Polynomial order of the shape functions (4 in this case) */ unsigned int order () const { return 4; } }; /**@ingroup LocalBasisImplementation \brief The local finite element needed for the Zou-Kornhuber estimator for Signorini problems This shape function set consists of three parts: - Linear shape functions associated to the element vertices - Piecewise linear edge bubbles - A cubic element bubble Currently this element exists only for triangles! The functions are associated to points by: f_0 ~ (0.0, 0.0) f_1 ~ (1.0, 0.0) f_2 ~ (0.0, 1.0) f_3 ~ (0.5, 0.0) f_4 ~ (0.0, 0.5) f_5 ~ (0.5, 0.5) f_6 ~ (1/3, 1/3) \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class HierarchicalSimplexP2WithElementBubbleLocalCoefficients { // The binomial coefficient: dim+1 over 1 static const int numVertices = dim+1; // The binomial coefficient: dim+1 over 2 static const int numEdges = (dim+1)*dim / 2; public: //! \brief Standard constructor HierarchicalSimplexP2WithElementBubbleLocalCoefficients () : li(numVertices+numEdges + 1) { if (dim!=2) DUNE_THROW(NotImplemented, "only for 2d"); li[0] = Dune::LocalKey(0,2,0); // Vertex (0,0) li[1] = Dune::LocalKey(0,1,0); // Edge (0.5, 0) li[2] = Dune::LocalKey(1,2,0); // Vertex (1,0) li[3] = Dune::LocalKey(1,1,0); // Edge (0, 0.5) li[4] = Dune::LocalKey(2,1,0); // Edge (0.5, 0.5) li[5] = Dune::LocalKey(2,2,0); // Vertex (0,1) li[6] = Dune::LocalKey(0,0,0); // Element (1/3, 1/3) } //! number of coefficients size_t size () const { return numVertices+numEdges + 1; } //! get i'th index const Dune::LocalKey& localKey (size_t i) const { return li[i]; } private: std::vector li; }; template class HierarchicalSimplexP2WithElementBubbleLocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; out.resize(7); // vertices x[0] = 0.0; x[1] = 0.0; f.evaluate(x,y); out[0] = y; x[0] = 1.0; x[1] = 0.0; f.evaluate(x,y); out[2] = y; x[0] = 0.0; x[1] = 1.0; f.evaluate(x,y); out[5] = y; // edge bubbles x[0] = 0.5; x[1] = 0.0; f.evaluate(x,y); out[1] = y - out[0]*(1-x[0]) - out[2]*x[0]; x[0] = 0.0; x[1] = 0.5; f.evaluate(x,y); out[3] = y - out[0]*(1-x[1]) - out[5]*x[1]; x[0] = 0.5; x[1] = 0.5; f.evaluate(x,y); out[4] = y - out[2]*x[0] - out[5]*x[1]; // element bubble x[0] = 1.0/3; x[1] = 1.0/3; f.evaluate(x,y); /** \todo Hack: extract the proper types */ HierarchicalSimplexP2WithElementBubbleLocalBasis shapeFunctions; std::vector sfValues; shapeFunctions.evaluateFunction(x, sfValues); out[6] = y; for (int i=0; i<6; i++) out[6] -= out[i]*sfValues[i]; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalprismp2.hh000066400000000000000000000041431313314431100303370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_HIERARCHICAL_PRISM_P2_LOCALFINITEELEMENT_HH #define DUNE_HIERARCHICAL_PRISM_P2_LOCALFINITEELEMENT_HH #include #include #include #include "hierarchicalprismp2/hierarchicalprismp2localbasis.hh" #include "hierarchicalprismp2/hierarchicalprismp2localinterpolation.hh" namespace Dune { /** \todo Please doc me ! */ template class HierarchicalPrismP2LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, PrismP2LocalCoefficients, HierarchicalPrismP2LocalInterpolation > > Traits; /** \todo Please doc me ! */ HierarchicalPrismP2LocalFiniteElement () { gt.makePrism(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } HierarchicalPrismP2LocalFiniteElement* clone () const { return new HierarchicalPrismP2LocalFiniteElement(*this); } private: HierarchicalPrismP2LocalBasis basis; /** \todo Stupid, Pk local coefficients can't be parametrized */ PrismP2LocalCoefficients coefficients; HierarchicalPrismP2LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalprismp2/000077500000000000000000000000001313314431100300145ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalprismp2/CMakeLists.txt000066400000000000000000000002741313314431100325570ustar00rootroot00000000000000install(FILES hierarchicalprismp2localbasis.hh hierarchicalprismp2localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/hierarchical/hierarchicalprismp2) hierarchicalprismp2localbasis.hh000066400000000000000000000204161313314431100362510ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalprismp2// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_HIERARCHICAL_PRISM_P2_LOCALBASIS_HH #define DUNE_HIERARCHICAL_PRISM_P2_LOCALBASIS_HH /** \file \brief Hierarchical prism p2 shape functions for the simplex */ #include #include #include #include namespace Dune { template class HierarchicalPrismP2LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 18; } //! \brief Evaluate all shape functions void evaluateFunction (const typename Traits::DomainType& in, std::vector & out) const { out.resize(18); out[0]=(1.0-in[0]-in[1])*(1.0-in[2]); out[1]= in[0]*(1-in[2]); out[2]=in[1]*(1-in[2]); out[3]=in[2]*(1.0-in[0]-in[1]); out[4]=in[0]*in[2]; out[5]=in[1]*in[2]; //edges out[6]=2*(1.0-in[0]-in[1])*(0.5-in[0]-in[1])*(4*in[2]-4*in[2]*in[2]); out[7]=2*in[0]*(-0.5+in[0])*(4*in[2]-4*in[2]*in[2]); out[8]=2*in[1]*(-0.5+in[1])*(4*in[2]-4*in[2]*in[2]); out[9]=4*in[0]*(1-in[0]-in[1])*(1-3*in[2]+2*in[2]*in[2]); out[10]=4*in[1]*(1-in[0]-in[1])*(1-3*in[2]+2*in[2]*in[2]); out[11]=4*in[0]*in[1]*(1-3*in[2]+2*in[2]*in[2]); out[12]=4*in[0]*(1-in[0]-in[1])*(-in[2]+2*in[2]*in[2]); out[13]=4*in[1]*(1-in[0]-in[1])*(-in[2]+2*in[2]*in[2]); out[14]=4*in[0]*in[1]*(-in[2]+2*in[2]*in[2]); //faces out[15]=4*in[0]*(1-in[0]-in[1])*(4*in[2]-4*in[2]*in[2]); out[16]=4*in[1]*(1-in[0]-in[1])*(4*in[2]-4*in[2]*in[2]); out[17]=4*in[0]*in[1]*(4*in[2]-4*in[2]*in[2]); } //! \brief Evaluate Jacobian of all shape functions void evaluateJacobian (const typename Traits::DomainType& in, //position std::vector& out) const //return value { out.resize(18); //vertices out[0][0][0] = in[2]-1; out[0][0][1] = in[2]-1; out[0][0][2] = in[0]+in[1]-1; out[1][0][0] = 1-in[2]; out[1][0][1] = 0; out[1][0][2] =-in[0]; out[2][0][0] = 0; out[2][0][1] = 1-in[2]; out[2][0][2] = -in[1]; out[3][0][0] = -in[2]; out[3][0][1] = -in[2]; out[3][0][2] = 1-in[0]-in[1]; out[4][0][0] = in[2]; out[4][0][1] = 0; out[4][0][2] = in[0]; out[5][0][0] = 0; out[5][0][1] = in[2]; out[5][0][2] = in[1]; //edges out[6][0][0] = (-3+4*in[0]+4*in[1])*(4*in[2]-4*in[2]*in[2]); out[6][0][1] = (-3+4*in[0]+4*in[1])*(4*in[2]-4*in[2]*in[2]); out[6][0][2] = 2*(1-in[0]-in[1])*(0.5-in[0]-in[1])*(4-8*in[2]); out[7][0][0] = (-1+4*in[0])*(4*in[2]-4*in[2]*in[2]); out[7][0][1] = 0; out[7][0][2] = 2*in[0]*(-0.5+in[0])*(4-8*in[2]); out[8][0][0] = 0; out[8][0][1] = (-1+4*in[1])*(4*in[2]-4*in[2]*in[2]); out[8][0][2] = 2*in[1]*(-0.5+in[1])*(4-8*in[2]); out[9][0][0] = (4-8*in[0]-4*in[1])*(1-3*in[2]+2*in[2]*in[2]); out[9][0][1] = -4*in[0]*(1-3*in[2]+2*in[2]*in[2]); out[9][0][2] = 4*in[0]*(1-in[0]-in[1])*(-3+4*in[2]); out[10][0][0] = (-4*in[1])*(1-3*in[2]+2*in[2]*in[2]); out[10][0][1] = (4-4*in[0]-8*in[1])*(1-3*in[2]+2*in[2]*in[2]); out[10][0][2] = 4*in[1]*(1-in[0]-in[1])*(-3+4*in[2]); out[11][0][0] = 4*in[1]*(1-3*in[2]+2*in[2]*in[2]); out[11][0][1] = 4*in[0]*(1-3*in[2]+2*in[2]*in[2]); out[11][0][2] = 4*in[0]*in[1]*(-3+4*in[2]); out[12][0][0] = (4-8*in[0]-4*in[1])*(-in[2]+2*in[2]*in[2]); out[12][0][1] = (-4*in[0])*(-in[2]+2*in[2]*in[2]); out[12][0][2] = 4*in[0]*(1-in[0]-in[1])*(-1+4*in[2]); out[13][0][0] = -4*in[1]*(-in[2]+2*in[2]*in[2]); out[13][0][1] = (4-4*in[0]-8*in[1])*(-in[2]+2*in[2]*in[2]); out[13][0][2] = 4*in[1]*(1-in[0]-in[1])*(-1+4*in[2]); out[14][0][0] = 4*in[1]*(-in[2]+2*in[2]*in[2]); out[14][0][1] = 4*in[0]*(-in[2]+2*in[2]*in[2]); out[14][0][2] = 4*in[0]*in[1]*(-1+4*in[2]); //faces out[15][0][0] = (4-8*in[0]-4*in[1])*(4*in[2]-4*in[2]*in[2]); out[15][0][1] = -4*in[0]*(4*in[2]-4*in[2]*in[2]); out[15][0][2] = 4*in[0]*(1-in[0]-in[1])*(4-8*in[2]); out[16][0][0] = -4*in[1]*(4*in[2]-4*in[2]*in[2]); out[16][0][1] = (4-4*in[0]-8*in[1])*(4*in[2]-4*in[2]*in[2]); out[16][0][2] = 4*in[1]*(1-in[0]-in[1])*(4-8*in[2]); out[17][0][0] = 4*in[1]*(4*in[2]-4*in[2]*in[2]); out[17][0][1] = 4*in[0]*(4*in[2]-4*in[2]*in[2]); out[17][0][2] = 4*in[0]*in[1]*(4-8*in[2]); } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0] = in[2]-1; out[1] = 1-in[2]; out[2] = 0; out[3] = -in[2]; out[4] = in[2]; out[5] = 0; out[6] = (-3+4*in[0]+4*in[1])*(4*in[2]-4*in[2]*in[2]); out[7] = (-1+4*in[0])*(4*in[2]-4*in[2]*in[2]); out[8] = 0; out[9] = (4-8*in[0]-4*in[1])*(1-3*in[2]+2*in[2]*in[2]); out[10] = (-4*in[1])*(1-3*in[2]+2*in[2]*in[2]); out[11] = 4*in[1]*(1-3*in[2]+2*in[2]*in[2]); out[12] = (4-8*in[0]-4*in[1])*(-in[2]+2*in[2]*in[2]); out[13] = -4*in[1]*(-in[2]+2*in[2]*in[2]); out[14] = 4*in[1]*(-in[2]+2*in[2]*in[2]); out[15] = (4-8*in[0]-4*in[1])*(4*in[2]-4*in[2]*in[2]); out[16] = -4*in[1]*(4*in[2]-4*in[2]*in[2]); out[17] = 4*in[1]*(4*in[2]-4*in[2]*in[2]); break; case 1: out[0] = in[2]-1; out[1] = 0; out[2] = 1-in[2]; out[3] = -in[2]; out[4] = 0; out[5] = in[2]; out[6] = (-3+4*in[0]+4*in[1])*(4*in[2]-4*in[2]*in[2]); out[7] = 0; out[8] = (-1+4*in[1])*(4*in[2]-4*in[2]*in[2]); out[9] = -4*in[0]*(1-3*in[2]+2*in[2]*in[2]); out[10] = (4-4*in[0]-8*in[1])*(1-3*in[2]+2*in[2]*in[2]); out[11] = 4*in[0]*(1-3*in[2]+2*in[2]*in[2]); out[12] = (-4*in[0])*(-in[2]+2*in[2]*in[2]); out[13] = (4-4*in[0]-8*in[1])*(-in[2]+2*in[2]*in[2]); out[14] = 4*in[0]*(-in[2]+2*in[2]*in[2]); out[15] = -4*in[0]*(4*in[2]-4*in[2]*in[2]); out[16] = (4-4*in[0]-8*in[1])*(4*in[2]-4*in[2]*in[2]); out[17] = 4*in[0]*(4*in[2]-4*in[2]*in[2]); break; case 2: out[0] = in[0]+in[1]-1; out[1] =-in[0]; out[2] = -in[1]; out[3] = 1-in[0]-in[1]; out[4] = in[0]; out[5] = in[1]; out[6] = 2*(1-in[0]-in[1])*(0.5-in[0]-in[1])*(4-8*in[2]); out[7] = 2*in[0]*(-0.5+in[0])*(4-8*in[2]); out[8] = 2*in[1]*(-0.5+in[1])*(4-8*in[2]); out[9] = 4*in[0]*(1-in[0]-in[1])*(-3+4*in[2]); out[10] = 4*in[1]*(1-in[0]-in[1])*(-3+4*in[2]); out[11] = 4*in[0]*in[1]*(-3+4*in[2]); out[12] = 4*in[0]*(1-in[0]-in[1])*(-1+4*in[2]); out[13] = 4*in[1]*(1-in[0]-in[1])*(-1+4*in[2]); out[14] = 4*in[0]*in[1]*(-1+4*in[2]); out[15] = 4*in[0]*(1-in[0]-in[1])*(4-8*in[2]); out[16] = 4*in[1]*(1-in[0]-in[1])*(4-8*in[2]); out[17] = 4*in[0]*in[1]*(4-8*in[2]); break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } /** \brief Polynomial order of the shape functions */ unsigned int order() const { return 2; } }; } #endif hierarchicalprismp2localinterpolation.hh000066400000000000000000000051331313314431100400360ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/hierarchical/hierarchicalprismp2// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_HIERARCHICAL_PRISM_P2_LOCALINTERPOLATION_HH #define DUNE_HIERARCHICAL_PRISM_P2_LOCALINTERPOLATION_HH #include namespace Dune { /** \tparam LB The LocalBasis implementation */ template class HierarchicalPrismP2LocalInterpolation { public: template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; out.resize(18); //First the vertex dofs x[0] = 0.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x, y); out[0] = y; x[0] = 1.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x, y); out[1] = y; x[0] = 0.0; x[1] = 1.0; x[2] = 0.0; f.evaluate(x, y); out[2] = y; x[0] = 0.0; x[1] = 0.0; x[2] = 1.0; f.evaluate(x, y); out[3] = y; x[0] = 1.0; x[1] = 0.0; x[2] = 1.0; f.evaluate(x, y); out[4] = y; x[0] = 0.0; x[1] = 1.0; x[2] = 1.0; f.evaluate(x, y); out[5] = y; // Then: the 9 edge dofs and the 3 face dofs x[0] = 0.0; x[1] = 0.0; x[2] = 0.5; f.evaluate(x, y); out[6] = y - 0.5*(out[0] + out[3]); x[0] = 1.0; x[1] = 0.0; x[2] = 0.5; f.evaluate(x, y); out[7] = y - 0.5*(out[1] + out[4]); x[0] = 0.0; x[1] = 1.0; x[2] = 0.5; f.evaluate(x, y); out[8] = y - 0.5*(out[2] + out[5]); x[0] = 0.5; x[1] = 0.0; x[2] = 0.0; f.evaluate(x, y); out[9] = y - 0.5*(out[0] + out[1]); x[0] = 0.0; x[1] = 0.5; x[2] = 0.0; f.evaluate(x, y); out[10] = y - 0.5*(out[2] + out[0]); x[0] = 0.5; x[1] = 0.5; x[2] = 0.0; f.evaluate(x, y); out[11] = y - 0.5*(out[2] + out[1]); x[0] = 0.5; x[1] = 0.0; x[2] = 1.0; f.evaluate(x, y); out[12] = y - 0.5*(out[3] + out[4]); x[0] = 0.0; x[1] = 0.5; x[2] = 1.0; f.evaluate(x, y); out[13] = y - 0.5*(out[3] + out[5]); x[0] = 0.5; x[1] = 0.5; x[2] = 1.0; f.evaluate(x, y); out[14] = y - 0.5*(out[4] + out[5]); //faces x[0] = 0.5; x[1] = 0.0; x[2] = 0.5; f.evaluate(x, y); out[15] = y - 0.25*(out[4] + out[1] + out[0] + out[3] ); x[0] = 0.0; x[1] = 0.5; x[2] = 0.5; f.evaluate(x, y); out[16] = y - 0.25*(out[2] + out[0] + out[3] + out[5] ); x[0] = 0.5; x[1] = 0.5; x[2] = 0.5; f.evaluate(x, y); out[17] = y - 0.25*(out[2] + out[1] + out[4] + out[5] ); } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange.hh000066400000000000000000000051341313314431100235470ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LAGRANGEFINITEELEMENT_HH #define DUNE_LAGRANGEFINITEELEMENT_HH #include #include #include #include #include namespace Dune { /** * @brief Lagrange local finite elements for a given set of interpolation * points. * * The class LP provides the points for the interpolation. * It has two template arguments, the first is the Field type to * use for evaluating the points the second the dimension * of the reference elements on which to construct the points. * It is instantiated with the desired order and has a template * method build taking a Topology to construct the points * (a std::vector of FieldVectors). * It also provides a static template method supports to indicate * if the point set can be build for a specified Topology. * * Examples include: * - EqualdistantPointSet: standard point set for lagrange points * - LobattoPointSet: an approximate Freget type point set * (provided for simplex and generalized prism * topologies (i.e. not for a 3d pyramid) * * \ingroup Lagrange * * \tparam LP a template class defining the points for the lagrange interpolation * \tparam dimDomain dimension of reference elements * \tparam D domain for basis functions * \tparam R range for basis functions * \tparam SF storage field for basis matrix * \tparam CF compute field for basis matrix **/ template< template class LP, unsigned int dimDomain, class D, class R, class SF=R, class CF=SF > class LagrangeLocalFiniteElement : public GenericLocalFiniteElement< LagrangeBasisFactory< LP, dimDomain, SF, CF >, LagrangeCoefficientsFactory, LagrangeInterpolationFactory< LP, dimDomain, SF > > { typedef GenericLocalFiniteElement< LagrangeBasisFactory< LP, dimDomain, SF, CF >, LagrangeCoefficientsFactory, LagrangeInterpolationFactory< LP, dimDomain, SF > > Base; public: typedef typename Base::Traits Traits; /** \todo Please doc me ! */ LagrangeLocalFiniteElement ( const GeometryType >, unsigned int order ) : Base( gt, order ) {} }; } #endif // #ifndef DUNE_LAGRANGEFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/lagrange/000077500000000000000000000000001313314431100232235ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/CMakeLists.txt000066400000000000000000000012161313314431100257630ustar00rootroot00000000000000add_subdirectory(p0) add_subdirectory(p1) add_subdirectory(p23d) add_subdirectory(pk1d) add_subdirectory(pk2d) add_subdirectory(pk3d) add_subdirectory(prismp1) add_subdirectory(prismp2) add_subdirectory(pyramidp1) add_subdirectory(pyramidp2) add_subdirectory(q1) add_subdirectory(qk) install(FILES emptypoints.hh equidistantpoints.hh interpolation.hh lagrangebasis.hh lagrangecoefficients.hh p0.hh p1.hh p23d.hh p2.hh pk1d.hh pk2d.hh pk3d.hh pk.hh pq22d.hh pqkfactory.hh prismp1.hh prismp2.hh pyramidp1.hh pyramidp2.hh q1.hh q2.hh qk.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/emptypoints.hh000066400000000000000000000035721313314431100261460ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LAGRANGE_EMPTYPOINTS_HH #define DUNE_LAGRANGE_EMPTYPOINTS_HH #include #include #include namespace Dune { template< class F, unsigned int dim > class LagrangePoint { typedef LagrangePoint< F, dim > This; template< class, class > friend class LagrangePointSetImpl; public: static const int dimension = dim; typedef F Field; typedef FieldVector< Field, dimension > Vector; const Vector &point () const { return point_; } const LocalKey &localKey () const { return localKey_; } Vector point_; LocalKey localKey_; }; // EmptyPointSet // -------------- template< class F, unsigned int dim > class EmptyPointSet { typedef EmptyPointSet< F, dim > This; public: typedef F Field; static const unsigned int dimension = dim; typedef Dune::LagrangePoint< Field, dimension > LagrangePoint; typedef typename std::vector< LagrangePoint >::const_iterator iterator; protected: EmptyPointSet ( const unsigned int order ) : order_( order ) {} public: const LagrangePoint &operator[] ( const unsigned int i ) const { assert( i < size() ); return points_[ i ]; } iterator begin () const { return points_.begin(); } iterator end () const { return points_.end(); } const LocalKey &localKey ( const unsigned int i ) const { return (*this)[ i ].localKey(); } unsigned int order () const { return order_; } unsigned int size () const { return points_.size(); } protected: unsigned int order_; std::vector< LagrangePoint > points_; }; } #endif // DUNE_LAGRANGE_EMPTYPOINTS_HH dune-localfunctions-2.5.1/dune/localfunctions/lagrange/equidistantpoints.hh000066400000000000000000000131171313314431100273360ustar00rootroot00000000000000#ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_EQUIDISTANTPOINTS_HH #define DUNE_LOCALFUNCTIONS_LAGRANGE_EQUIDISTANTPOINTS_HH #include #include #include #include #include #include #include namespace Dune { // numLagrangePoints // ----------------- inline std::size_t numLagrangePoints ( unsigned int topologyId, int dim, unsigned int order ) { assert( topologyId < Impl::numTopologies( dim ) ); if( dim > 0 ) { const unsigned int baseId = Impl::baseTopologyId( topologyId, dim ); if( Impl::isPyramid( topologyId, dim ) ) { std::size_t size = 0; for( unsigned int o = 0; o <= order; ++o ) size += numLagrangePoints( baseId, dim-1, o ); return size; } else return numLagrangePoints( baseId, dim-1, order ) * (order+1); } else return 1; } // equidistantLagrangePoints // ------------------------- template< class ct, unsigned int cdim > inline static unsigned int equidistantLagrangePoints ( unsigned int topologyId, unsigned int dim, unsigned int codim, unsigned int order, unsigned int *count, LagrangePoint< ct, cdim > *points ) { assert( (0 <= codim) && (codim <= dim) && (dim <= cdim) ); assert( topologyId < Impl::numTopologies( dim ) ); if( dim > 0 ) { const unsigned int baseId = Impl::baseTopologyId( topologyId, dim ); const unsigned int numBaseN = (codim < dim ? Impl::size( baseId, dim-1, codim ) : 0); const unsigned int numBaseM = (codim > 0 ? Impl::size( baseId, dim-1, codim-1 ) : 0); if( Impl::isPrism( topologyId, dim ) ) { unsigned int size = 0; if( codim < dim ) { for( unsigned int i = 1; i < order; ++i ) { const unsigned int n = equidistantLagrangePoints( baseId, dim-1, codim, order, count, points ); for( unsigned int j = 0; j < n; ++j ) { LocalKey &key = points->localKey_; key = LocalKey( key.subEntity(), codim, key.index() ); points->point_[ dim-1 ] = ct( i ) / ct( order ); ++points; } size += n; } } if( codim > 0 ) { const unsigned int n = equidistantLagrangePoints( baseId, dim-1, codim-1, order, count+numBaseN, points ); for( unsigned int j = 0; j < n; ++j ) { LocalKey &key = points[ j ].localKey_; key = LocalKey( key.subEntity() + numBaseN, codim, key.index() ); points[ j + n ].point_ = points[ j ].point_; points[ j + n ].point_[ dim-1 ] = ct( 1 ); points[ j + n ].localKey_ = LocalKey( key.subEntity() + numBaseM, codim, key.index() ); ++count[ key.subEntity() + numBaseM ]; } size += 2*n; } return size; } else { unsigned int size = (codim > 0 ? equidistantLagrangePoints( baseId, dim-1, codim-1, order, count, points ) : 0); LagrangePoint< ct, cdim > *const end = points + size; for( ; points != end; ++points ) points->localKey_ = LocalKey( points->localKey_.subEntity(), codim, points->localKey_.index() ); if( codim < dim ) { for( unsigned int i = order-1; i > 0; --i ) { const unsigned int n = equidistantLagrangePoints( baseId, dim-1, codim, i, count+numBaseM, points ); LagrangePoint< ct, cdim > *const end = points + n; for( ; points != end; ++points ) { points->localKey_ = LocalKey( points->localKey_.subEntity()+numBaseM, codim, points->localKey_.index() ); for( unsigned int j = 0; j < dim-1; ++j ) points->point_[ j ] *= ct( i ) / ct( order ); points->point_[ dim-1 ] = ct( order - i ) / ct( order ); } size += n; } } else { points->localKey_ = LocalKey( numBaseM, dim, count[ numBaseM ]++ ); points->point_ = 0; points->point_[ dim-1 ] = ct( 1 ); ++size; } return size; } } else { points->localKey_ = LocalKey( 0, 0, count[ 0 ]++ ); points->point_ = 0; return 1; } } // EquidistantPointSet // ------------------- template< class F, unsigned int dim > class EquidistantPointSet : public EmptyPointSet< F, dim > { typedef EmptyPointSet< F, dim > Base; public: static const unsigned int dimension = dim; using Base::order; EquidistantPointSet ( unsigned int order ) : Base( order ) {} void build ( GeometryType gt ) { assert( gt.dim() == dimension ); points_.resize( numLagrangePoints( gt.id(), dimension, order() ) ); typename Base::LagrangePoint *p = points_.data(); std::vector< unsigned int > count; for( unsigned int mydim = 0; mydim <= dimension; ++mydim ) { count.resize( Impl::size( gt.id(), dimension, dimension-mydim ) ); std::fill( count.begin(), count.end(), 0u ); p += equidistantLagrangePoints( gt.id(), dimension, dimension-mydim, order(), count.data(), p ); } } template< class T > bool build () { build( GeometryType( T() ) ); return true; } template< class T > static bool supports ( unsigned int order ) { return true; } private: using Base::points_; }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_EQUIDISTANTPOINTS_HH dune-localfunctions-2.5.1/dune/localfunctions/lagrange/interpolation.hh000066400000000000000000000077231313314431100264440ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LAGRANGEBASIS_INTERPOLATION_HH #define DUNE_LAGRANGEBASIS_INTERPOLATION_HH #include #include #include namespace Dune { template< template class LP, unsigned int dim, class F > struct LagrangeInterpolationFactory; // LocalLagrangeInterpolation // -------------------------- template< template class LP, unsigned int dim, class F > class LocalLagrangeInterpolation { typedef LocalLagrangeInterpolation< LP,dim,F > This; public: typedef LP LagrangePointSet; typedef typename LagrangePointSet::Field Field; static const unsigned int dimension = LagrangePointSet::dimension; private: friend struct LagrangeInterpolationFactory; const LagrangePointSet &lagrangePoints_; explicit LocalLagrangeInterpolation ( const LagrangePointSet &lagrangePoints ) : lagrangePoints_( lagrangePoints ) {} const LagrangePointSet *points () const { return &lagrangePoints_; } public: template< class Function, class Fy > void interpolate ( const Function &function, std::vector< Fy > &coefficients ) const { typedef typename LagrangePointSet::iterator Iterator; coefficients.resize( lagrangePoints_.size() ); unsigned int index = 0; const Iterator end = lagrangePoints_.end(); for( Iterator it = lagrangePoints_.begin(); it != end; ++it ) { typename Function::RangeType val; function.evaluate( field_cast(it->point()), val ); field_cast( val, coefficients[ index++ ] ); } } template< class Matrix, class Basis > void interpolate ( const Basis &basis, Matrix &coefficients ) const { typedef typename LagrangePointSet::iterator Iterator; coefficients.resize( lagrangePoints_.size(), basis.size( ) ); unsigned int index = 0; const Iterator end = lagrangePoints_.end(); for( Iterator it = lagrangePoints_.begin(); it != end; ++it ) basis.template evaluate<0>( it->point(), coefficients.rowPtr( index++ ) ); } const LagrangePointSet &lagrangePoints () const { return lagrangePoints_; } }; // LocalLagrangeInterpolationFactory // --------------------------------- template< template class LP, unsigned int dim, class F > struct LagrangeInterpolationFactoryTraits { typedef LagrangeCoefficientsFactory LagrangePointSetFactory; typedef typename LagrangePointSetFactory::Object LagrangePointSet; typedef typename LagrangePointSetFactory::Key Key; typedef const LocalLagrangeInterpolation< LP,dim,F > Object; typedef LagrangeInterpolationFactory Factory; static const unsigned int dimension = dim; }; template< template class LP, unsigned int dim, class F > struct LagrangeInterpolationFactory : public TopologyFactory< LagrangeInterpolationFactoryTraits< LP,dim,F > > { typedef LagrangeInterpolationFactoryTraits< LP,dim,F > Traits; typedef typename Traits::Key Key; typedef typename Traits::Object Object; template< class Topology > static Object *createObject ( const Key &key ) { const typename Traits::LagrangePointSet *lagrangeCoeff = Traits::LagrangePointSetFactory::template create< Topology >( key ); if ( lagrangeCoeff == 0 ) return 0; else return new Object( *lagrangeCoeff ); } template< class Topology > static bool supports ( const typename Traits::Key &key ) { return true; } static void release( Object *object) { Traits::LagrangePointSetFactory::release( object->points() ); delete object; } }; } #endif // #ifndef DUNE_LAGRANGEBASIS_INTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/lagrange/lagrangebasis.hh000066400000000000000000000013261313314431100263500ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LAGRANGEBASIS_HH #define DUNE_LAGRANGEBASIS_HH #include #include #include #include #include namespace Dune { template< template class LP, unsigned int dim, class SF, class CF > struct LagrangeBasisFactory : public DefaultBasisFactory< MonomialBasisFactory, LagrangeInterpolationFactory, dim,1,SF,CF > {}; } #endif // #ifndef DUNE_LAGRANGEBASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/lagrange/lagrangecoefficients.hh000066400000000000000000000033151313314431100277100ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LAGRANGECOEFFICIENTS_HH #define DUNE_LAGRANGECOEFFICIENTS_HH #include #include #include #include #include #include namespace Dune { template< template class LP, unsigned int dim, class F > struct LagrangeCoefficientsFactory; template< template class LP, unsigned int dim, class F> struct LagrangeCoefficientsFactoryTraits { static const unsigned int dimension = dim; const typedef LP Object; typedef unsigned int Key; typedef LagrangeCoefficientsFactory< LP,dim,F > Factory; }; template< template class LP, unsigned int dim, class F> struct LagrangeCoefficientsFactory : public TopologyFactory< LagrangeCoefficientsFactoryTraits< LP,dim,F> > { typedef LagrangeCoefficientsFactoryTraits Traits; static const unsigned int dimension = dim; typedef typename Traits::Object Object; typedef typename Traits::Key Key; template< class T > static Object *createObject ( const Key &order ) { if (order == 0 || !Object::template supports(order)) return 0; typedef typename std::remove_const::type LagrangeCoefficients; LagrangeCoefficients *object = new LagrangeCoefficients(order); if ( !object->template build() ) { delete object; object = nullptr; } return object; } }; } #endif // DUNE_LAGRANGECOEFFICIENTS_HH dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p0.hh000066400000000000000000000036141313314431100240670ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P0LOCALFINITEELEMENT_HH #define DUNE_P0LOCALFINITEELEMENT_HH #include #include #include "p0/p0localbasis.hh" #include "p0/p0localcoefficients.hh" #include "p0/p0localinterpolation.hh" namespace Dune { /** \brief The local p0 finite element on all types of reference elements \tparam D Domain data type \tparam R Range data type \tparam d Dimension of the reference element */ template class P0LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, P0LocalCoefficients, P0LocalInterpolation > > Traits; /** \todo Please doc me ! */ P0LocalFiniteElement (const GeometryType& type) : interpolation(type), gt(type) {} /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief The number of shape functions -- here: 1 */ unsigned int size () const { return 1; } /** \todo Please doc me ! */ GeometryType type () const { return gt; } P0LocalFiniteElement* clone () const { return new P0LocalFiniteElement(*this); } private: P0LocalBasis basis; P0LocalCoefficients coefficients; P0LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p0/000077500000000000000000000000001313314431100235425ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p0/CMakeLists.txt000066400000000000000000000002361313314431100263030ustar00rootroot00000000000000install(FILES p0localbasis.hh p0localcoefficients.hh p0localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/p0) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p0/p0localbasis.hh000066400000000000000000000046401313314431100264430ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P0LOCALBASIS_HH #define DUNE_P0LOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Constant shape function Defines the constant scalar shape function in d dimensions. Is valid on any type of reference element. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam d Domain dimension \nosubgrouping */ template class P0LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix, 0> Traits; //! \brief number of shape functions unsigned int size () const { return 1; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(1); out[0] = 1; } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(1); for (int i=0; i& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { out.resize(1); out[0] = 0; } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 0; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p0/p0localcoefficients.hh000066400000000000000000000015011313314431100277740ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P0LOCALCOEFFICIENTS_HH #define DUNE_P0LOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for P0 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class P0LocalCoefficients { public: //! \brief Standard constructor P0LocalCoefficients () : index(0,0,0) {} //! number of coefficients std::size_t size () const { return 1; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return index; } private: LocalKey index; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p0/p0localinterpolation.hh000066400000000000000000000017251313314431100302320ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P0LOCALINTERPOLATION_HH #define DUNE_P0LOCALINTERPOLATION_HH #include #include namespace Dune { template class P0LocalInterpolation { public: P0LocalInterpolation (const GeometryType& gt) : gt_(gt) {} //! determine coefficients interpolating a given function template void interpolate (const F& f, std::vector& out) const { typedef typename LB::Traits::DomainType DomainType; typedef typename LB::Traits::RangeType RangeType; typedef typename LB::Traits::DomainFieldType DF; const int dim=LB::Traits::dimDomain; DomainType x = Dune::ReferenceElements::general(gt_).position(0,0); RangeType y; out.resize(1); f.evaluate(x,y); out[0] = y; } private: GeometryType gt_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p1.hh000066400000000000000000000036001313314431100240630ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P1LOCALFINITEELEMENT_HH #define DUNE_P1LOCALFINITEELEMENT_HH #include #include #include "p1/p1localbasis.hh" #include "p1/p1localcoefficients.hh" #include "p1/p1localinterpolation.hh" namespace Dune { /** \brief The local p1 finite element on simplices \tparam D Domain data type \tparam R Range data type \tparam dim Dimension of the simplex */ template class P1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits,P1LocalCoefficients, P1LocalInterpolation > > Traits; /** \todo Please doc me ! */ P1LocalFiniteElement () { gt.makeSimplex(dim); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } P1LocalFiniteElement* clone () const { return new P1LocalFiniteElement(*this); } private: P1LocalBasis basis; P1LocalCoefficients coefficients; P1LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p1/000077500000000000000000000000001313314431100235435ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p1/CMakeLists.txt000066400000000000000000000002361313314431100263040ustar00rootroot00000000000000install(FILES p1localbasis.hh p1localcoefficients.hh p1localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/p1) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p1/p1localbasis.hh000066400000000000000000000072761313314431100264550ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P1_LOCALBASIS_HH #define DUNE_P1_LOCALBASIS_HH #include #include #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Linear Lagrange shape functions on the simplex. Defines the linear shape functions on the simplex. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam dim The dimension of the simplex \nosubgrouping */ template class P1LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix, 2> Traits; //! \brief number of shape functions unsigned int size () const { return dim+1; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); out[0] = 1.0; for (size_t i=0; i& out) const // return value { out.resize(size()); for (int i=0; i& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder==0) evaluateFunction(in, out); else if (totalOrder==1) { auto direction = std::find(order.begin(), order.end(), 1); out.resize(size()); out[0] = -1; for (int i=0; i inline void DUNE_DEPRECATED_MSG("Use method 'partial' instead!") evaluate (const typename std::array& directions, const typename Traits::DomainType& in, std::vector& out) const { if (k==0) evaluateFunction(in, out); else if (k==1) { out.resize(size()); out[0] = -1; for (int i=0; i #include #include #include namespace Dune { /** \brief Local coefficients for simplex P1 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class P1LocalCoefficients { public: //! \brief Standard constructor P1LocalCoefficients () : li(size()) { for (std::size_t i=0; i li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p1/p1localinterpolation.hh000066400000000000000000000015111313314431100302250ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P1_LOCALINTERPOLATION_HH #define DUNE_P1_LOCALINTERPOLATION_HH #include namespace Dune { template class P1LocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; typename LB::Traits::DomainType x; out.resize(dim+1); // vertex 0 for (int i=0; i class P2LocalFiniteElement; /** \todo Please doc me ! */ template class P2LocalFiniteElement : public Pk2DLocalFiniteElement {}; /** \todo Please doc me ! */ template class P2LocalFiniteElement : public P23DLocalFiniteElement {}; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p23d.hh000066400000000000000000000034011313314431100243120ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P2_3DLOCALFINITEELEMENT_HH #define DUNE_P2_3DLOCALFINITEELEMENT_HH #include #include #include "p23d/p23dlocalbasis.hh" #include "p23d/p23dlocalcoefficients.hh" #include "p23d/p23dlocalinterpolation.hh" namespace Dune { /** \todo Please doc me ! */ template class P23DLocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, P23DLocalCoefficients, P23DLocalInterpolation > > Traits; /** \todo Please doc me ! */ P23DLocalFiniteElement () { gt.makeTetrahedron(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } P23DLocalFiniteElement* clone () const { return new P23DLocalFiniteElement(*this); } private: P23DLocalBasis basis; P23DLocalCoefficients coefficients; P23DLocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p23d/000077500000000000000000000000001313314431100237735ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p23d/CMakeLists.txt000066400000000000000000000002461313314431100265350ustar00rootroot00000000000000install(FILES p23dlocalbasis.hh p23dlocalcoefficients.hh p23dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/p23d) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p23d/p23dlocalbasis.hh000066400000000000000000000302401313314431100271200ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P2_3DLOCALBASIS_HH #define DUNE_P2_3DLOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Quadratic Lagrange shape functions on the tetrahedron. Defines the quadratic shape functions on tetrahedron. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class P23DLocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 10; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(10); int coeff; R a[2], b[3], c[3]; // case 0: coeff=2; a[0]=1.0; a[1]=0.5; b[0]=-1.0; b[1]=-1.0; b[2]=-1.0; c[0]=-1.0; c[1]=-1.0; c[2]=-1.0; out[0] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 1: coeff=2; a[0]=0.0; a[1]=-0.5; b[0]=1.0; b[1]=0.0; b[2]=0.0; c[0]=1.0; c[1]=0.0; c[2]=0.0; out[1] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 2: coeff=2; a[0]=0.0; a[1]=-0.5; b[0]=0.0; b[1]=1.0; b[2]=0.0; c[0]=0.0; c[1]=1.0; c[2]=0.0; out[2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 3: coeff=2; a[0]=0.0; a[1]=-0.5; b[0]=0.0; b[1]=0.0; b[2]=1.0; c[0]=0.0; c[1]=0.0; c[2]=1.0; out[3] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 4: coeff=4; a[0]=0.0; a[1]=1.0; b[0]=1.0; b[1]=0.0; b[2]=0.0; c[0]=-1.0; c[1]=-1.0; c[2]=-1.0; out[4] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 5: coeff=4; a[0]=0.0; a[1]=0.0; b[0]=1.0; b[1]=0.0; b[2]=0.0; c[0]=0.0; c[1]=1.0; c[2]=0.0; out[5] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 6: coeff=4; a[0]=0.0; a[1]=1.0; b[0]=0.0; b[1]=1.0; b[2]=0.0; c[0]=-1.0; c[1]=-1.0; c[2]=-1.0; out[6] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 7: coeff=4; a[0]=0.0; a[1]=1.0; b[0]=0.0; b[1]=0.0; b[2]=1.0; c[0]=-1.0; c[1]=-1.0; c[2]=-1.0; out[7] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 8: coeff=4; a[0]=0.0; a[1]=0.0; b[0]=1.0; b[1]=0.0; b[2]=0.0; c[0]=0.0; c[1]=0.0; c[2]=1.0; out[8] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); // case 9: coeff=4; a[0]=0.0; a[1]=0.0; b[0]=0.0; b[1]=1.0; b[2]=0.0; c[0]=0.0; c[1]=0.0; c[2]=1.0; out[9] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1] + b[2]*in[2]) * (a[1] + c[0]*in[0] + c[1]*in[1] + c[2]*in[2]); } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(10); R aa[3][3], bb[3][3]; // case 0: //x derivative aa[0][0]=-3.0; bb[0][0]=4.0; bb[1][0]=4.0; bb[2][0]=4.0; //y derivative aa[0][1]=-3.0; bb[0][1]=4.0; bb[1][1]=4.0; bb[2][1]=4.0; // z derivative aa[0][2]=-3.0; bb[0][2]=4.0; bb[1][2]=4.0; bb[2][2]=4.0; out[0][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[0][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[0][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; //case 1: //x derivative aa[0][0]=-1.0; bb[0][0]=4.0; bb[1][0]=0.0; bb[2][0]=0.0; //y derivative aa[0][1]=0.0; bb[0][1]=0.0; bb[1][1]=0.0; bb[2][1]=0.0; // z derivative aa[0][2]=0.0; bb[0][2]=0.0; bb[1][2]=0.0; bb[2][2]=0.0; out[1][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[1][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[1][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; // case 2: //x derivative aa[0][0]=0.0; bb[0][0]=0.0; bb[1][0]=0.0; bb[2][0]=0.0; //y derivative aa[0][1]=-1.0; bb[0][1]=0.0; bb[1][1]=4.0; bb[2][1]=0.0; // z derivative aa[0][2]=0.0; bb[0][2]=0.0; bb[1][2]=0.0; bb[2][2]=0.0; out[2][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[2][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[2][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; // case 3: //x derivative aa[0][0]=0.0; bb[0][0]=0.0; bb[1][0]=0.0; bb[2][0]=0.0; //y derivative aa[0][1]=0.0; bb[0][1]=0.0; bb[1][1]=0.0; bb[2][1]=0.0; // z derivative aa[0][2]=-1.0; bb[0][2]=0.0; bb[1][2]=0.0; bb[2][2]=4.0; out[3][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[3][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[3][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; // case 4: //x derivative aa[0][0]=4.0; bb[0][0]=-8.0; bb[1][0]=-4.0; bb[2][0]=-4.0; //y derivative aa[0][1]=0.0; bb[0][1]=-4.0; bb[1][1]=0.0; bb[2][1]=0.0; // z derivative aa[0][2]=0.0; bb[0][2]=-4.0; bb[1][2]=0.0; bb[2][2]=0.0; out[4][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[4][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[4][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; // case 5: //x derivative aa[0][0]=0.0; bb[0][0]=0.0; bb[1][0]=4.0; bb[2][0]=0.0; //y derivative aa[0][1]=0.0; bb[0][1]=4.0; bb[1][1]=0.0; bb[2][1]=0.0; // z derivative aa[0][2]=0.0; bb[0][2]=0.0; bb[1][2]=0.0; bb[2][2]=0.0; out[5][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[5][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[5][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; // case 6: //x derivative aa[0][0]=0.0; bb[0][0]=0.0; bb[1][0]=-4.0; bb[2][0]=0.0; //y derivative aa[0][1]=4.0; bb[0][1]=-4.0; bb[1][1]=-8.0; bb[2][1]=-4.0; // z derivative aa[0][2]=0.0; bb[0][2]=0.0; bb[1][2]=-4.0; bb[2][2]=0.0; out[6][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[6][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[6][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; // case 7: //x derivative aa[0][0]=0.0; bb[0][0]=0.0; bb[1][0]=0.0; bb[2][0]=-4.0; //y derivative aa[0][1]=0.0; bb[0][1]=0.0; bb[1][1]=0.0; bb[2][1]=-4.0; // z derivative aa[0][2]=4.0; bb[0][2]=-4.0; bb[1][2]=-4.0; bb[2][2]=-8.0; out[7][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[7][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[7][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; //case 8: //x derivative aa[0][0]=0.0; bb[0][0]=0.0; bb[1][0]=0.0; bb[2][0]=4.0; //y derivative aa[0][1]=0.0; bb[0][1]=0.0; bb[1][1]=0.0; bb[2][1]=0.0; // z derivative aa[0][2]=0.0; bb[0][2]=4.0; bb[1][2]=0.0; bb[2][2]=0.0; out[8][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[8][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[8][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; // case 9: //x derivative aa[0][0]=0.0; bb[0][0]=0.0; bb[1][0]=0.0; bb[2][0]=0.0; //y derivative aa[0][1]=0.0; bb[0][1]=0.0; bb[1][1]=0.0; bb[2][1]=4.0; // z derivative aa[0][2]=0.0; bb[0][2]=0.0; bb[1][2]=4.0; bb[2][2]=0.0; out[9][0][0] = aa[0][0] + bb[0][0]*in[0] + bb[1][0]*in[1] + bb[2][0]*in[2]; out[9][0][1] = aa[0][1] + bb[0][1]*in[0] + bb[1][1]*in[1] + bb[2][1]*in[2]; out[9][0][2] = aa[0][2] + bb[0][2]*in[0] + bb[1][2]*in[1] + bb[2][2]*in[2]; } /** \brief Evaluate partial derivatives of any order of all shape functions * \param order Order of the partial derivatives, in the classic multi-index notation * \param in Position where to evaluate the derivatives * \param[out] out Return value: the desired partial derivatives */ void partial(const std::array& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0] =-3.0 + 4.0*(in[0] + in[1] + in[2]); out[1] =-1.0 + 4.0*in[0]; out[2] = 0.0; out[3] = 0.0; out[4] = 4.0 - 4.0*(2.0*in[0] + in[1] + in[2]); out[5] = 4.0*in[1]; out[6] =-4.0*in[1]; out[7] =-4.0*in[2]; out[8] = 4.0*in[2]; out[9] = 0.0; break; case 1: out[0] =-3.0 + 4.0*(in[0] + in[1] + in[2]); out[1] = 0.0; out[2] =-1.0 + 4.0*in[1]; out[3] = 0.0; out[4] =-4.0*in[0]; out[5] = 4.0*in[0]; out[6] = 4.0 - 4.0*(in[0] + 2.0*in[1] + in[2]); out[7] =-4.0*in[2]; out[8] = 0.0; out[9] = 4.0*in[2]; break; case 2: out[0] =-3.0 + 4.0*(in[0] + in[1] + in[2]); out[1] = 0.0; out[2] = 0.0; out[3] =-1.0 + 4.0*in[2]; out[4] =-4.0*in[0]; out[5] = 0.0; out[6] =-4.0*in[1]; out[7] = 4.0 - 4.0*(in[0] + in[1] + 2.0*in[2]); out[8] = 4.0*in[0]; out[9] = 4.0*in[1]; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 2; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p23d/p23dlocalcoefficients.hh000066400000000000000000000022611313314431100304620ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P2_3DLOCALCOEFFICIENTS_HH #define DUNE_P2_3DLOCALCOEFFICIENTS_HH #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for P23D elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class P23DLocalCoefficients { public: //! \brief Standard constructor P23DLocalCoefficients () : li(10) { // Vertex shape functions li[0] = LocalKey(0,3,0); li[1] = LocalKey(1,3,0); li[2] = LocalKey(2,3,0); li[3] = LocalKey(3,3,0); // Edge bubbles li[4] = LocalKey(0,2,0); li[5] = LocalKey(2,2,0); li[6] = LocalKey(1,2,0); li[7] = LocalKey(3,2,0); li[8] = LocalKey(4,2,0); li[9] = LocalKey(5,2,0); } //! number of coefficients std::size_t size () const { return 10; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/p23d/p23dlocalinterpolation.hh000066400000000000000000000025431313314431100307130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P2_3DLOCALINTERPOLATION_HH #define DUNE_P2_3DLOCALINTERPOLATION_HH #include namespace Dune { template class P23DLocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; out.resize(10); typename LB::Traits::DomainType x; x[0] = 0.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[0] = y; x[0] = 1.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[1] = y; x[0] = 0.0; x[1] = 1.0; x[2] = 0.0; f.evaluate(x,y); out[2] = y; x[0] = 0.0; x[1] = 0.0; x[2] = 1.0; f.evaluate(x,y); out[3] = y; x[0] = 0.5; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[4] = y; x[0] = 0.5; x[1] = 0.5; x[2] = 0.0; f.evaluate(x,y); out[5] = y; x[0] = 0.0; x[1] = 0.5; x[2] = 0.0; f.evaluate(x,y); out[6] = y; x[0] = 0.0; x[1] = 0.0; x[2] = 0.5; f.evaluate(x,y); out[7] = y; x[0] = 0.5; x[1] = 0.0; x[2] = 0.5; f.evaluate(x,y); out[8] = y; x[0] = 0.0; x[1] = 0.5; x[2] = 0.5; f.evaluate(x,y); out[9] = y; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk.hh000066400000000000000000000070451313314431100241640ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /* vim: set ai expandtab sw=4 ts=4: */ #ifndef DUNE_PK_LOCALFINITEELEMENT_HH #define DUNE_PK_LOCALFINITEELEMENT_HH #include "p0.hh" #include "p1.hh" #include "pk1d.hh" #include "pk2d.hh" #include "pk3d.hh" namespace Dune { /** \brief General Lagrange finite element with arbitrary dimension and polynomial order * * \tparam D type used for domain coordinates * \tparam R type used for function values * \tparam d dimension of the reference element * \tparam k polynomial order */ template class PkLocalFiniteElement { public: PkLocalFiniteElement() {} /** Constructor for variants with permuted vertices. \param vertexmap The permutation of the vertices. This can for instance be generated from the global indices of the vertices by reducing those to the integers 0...k+1 */ PkLocalFiniteElement(const unsigned int vertexmap[k+1]) {} }; #if 0 /** \brief General Lagrange finite element -- specialization for first-order on a 1d reference element * * \tparam D type used for domain coordinates * \tparam R type used for function values */ template class PkLocalFiniteElement : public P1LocalFiniteElement { public: PkLocalFiniteElement() {} PkLocalFiniteElement(const unsigned int vertexmap[2]) {} }; /** \brief General Lagrange finite element -- specialization for zero-th order on a 1d reference element * * \tparam D type used for domain coordinates * \tparam R type used for function values * \tparam d dimension of the reference element */ template class PkLocalFiniteElement : public P0LocalFiniteElement { public: PkLocalFiniteElement() : P0LocalFiniteElement(GeometryType(0,1)) {} PkLocalFiniteElement(const unsigned int vertexmap[2]) {} }; #endif /** \brief General Lagrange finite element -- specialization for a 2d reference element * * \tparam D type used for domain coordinates * \tparam R type used for function values * \tparam k polynomial order */ template class PkLocalFiniteElement : public Pk1DLocalFiniteElement { public: PkLocalFiniteElement() {} PkLocalFiniteElement(const unsigned int vertexmap[2]) : Pk1DLocalFiniteElement(vertexmap) {} }; /** \brief General Lagrange finite element -- specialization for a 2d reference element * * \tparam D type used for domain coordinates * \tparam R type used for function values * \tparam k polynomial order */ template class PkLocalFiniteElement : public Pk2DLocalFiniteElement { public: PkLocalFiniteElement() {} PkLocalFiniteElement(const unsigned int vertexmap[3]) : Pk2DLocalFiniteElement(vertexmap) {} }; /** \brief General Lagrange finite element -- specialization for a 3d reference element * * \tparam D type used for domain coordinates * \tparam R type used for function values * \tparam k polynomial order */ template class PkLocalFiniteElement : public Pk3DLocalFiniteElement { public: PkLocalFiniteElement() {} PkLocalFiniteElement(const unsigned int vertexmap[4]) : Pk3DLocalFiniteElement(vertexmap) {} }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk1d.hh000066400000000000000000000155431313314431100244130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PK1DLOCALFINITEELEMENT_HH #define DUNE_PK1DLOCALFINITEELEMENT_HH #include #include #include #include #include "pk1d/pk1dlocalbasis.hh" #include "pk1d/pk1dlocalcoefficients.hh" #include "pk1d/pk1dlocalinterpolation.hh" namespace Dune { /** \todo Please doc me ! */ template class Pk1DLocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, Pk1DLocalCoefficients, Pk1DLocalInterpolation > > Traits; /** \todo Please doc me ! */ Pk1DLocalFiniteElement () { gt.makeLine(); } /** \todo Please doc me ! */ Pk1DLocalFiniteElement (int variant) : coefficients(variant) { gt.makeLine(); } /** Constructor for two variants with permuted vertices. \param vertexmap The permutation of the vertices. */ Pk1DLocalFiniteElement (const unsigned int vertexmap[3]) : coefficients(vertexmap) { gt.makeLine(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } Pk1DLocalFiniteElement* clone () const { return new Pk1DLocalFiniteElement(*this); } private: Pk1DLocalBasis basis; Pk1DLocalCoefficients coefficients; Pk1DLocalInterpolation > interpolation; GeometryType gt; }; //! Langrange finite element of arbitrary order on triangles /** * \tparam Geometry Geometry for the local to global transformation. * \tparam RF Field type of the range. * \tparam k Maximum polynomial order of the base functions. * * \implements FiniteElementInterface */ template class Pk1DFiniteElement { typedef typename Geometry::ctype DF; typedef Pk1DLocalBasis LocalBasis; typedef Pk1DLocalInterpolation LocalInterpolation; public: /** * \implements FiniteElementInterface::Traits */ struct Traits { typedef ScalarLocalToGlobalBasisAdaptor Basis; typedef LocalToGlobalInterpolationAdaptor< LocalInterpolation, typename Basis::Traits > Interpolation; typedef Pk1DLocalCoefficients Coefficients; }; private: static const GeometryType gt; static const LocalBasis localBasis; static const LocalInterpolation localInterpolation; typename Traits::Basis basis_; typename Traits::Interpolation interpolation_; typename Traits::Coefficients coefficients_; public: //! construct a Pk1DFiniteElement /** * \param geometry The geometry object to use for adaption. * \param vertexOrder The global ordering of the vertices within the grid, * used to determine orientation of the edges. This * vertexOrder object must support codim=0. * * \note This class stores the reference to the geometry passed here. Any * use of this class after this references has become invalid * results in undefined behaviour. The exception is that the * destructor of this class may still be called. The information * contained in the vertexOrder object is extracted and the object * is no longer needed after the contructor returns. */ template Pk1DFiniteElement(const Geometry &geometry, const VertexOrder& vertexOrder) : basis_(localBasis, geometry), interpolation_(localInterpolation), coefficients_(vertexOrder.begin(0, 0)) { } const typename Traits::Basis& basis() const { return basis_; } const typename Traits::Interpolation& interpolation() const { return interpolation_; } const typename Traits::Coefficients& coefficients() const { return coefficients_; } const GeometryType &type() const { return gt; } }; template const GeometryType Pk1DFiniteElement::gt(GeometryType::simplex, 2); template const typename Pk1DFiniteElement::LocalBasis Pk1DFiniteElement::localBasis = LocalBasis(); template const typename Pk1DFiniteElement::LocalInterpolation Pk1DFiniteElement::localInterpolation = LocalInterpolation(); //! Factory for Pk1DFiniteElement objects /** * Constructs Pk1DFiniteElement objects given a geometry and a vertex * ordering. * * \tparam Geometry Geometry for the local to global transformation. * \tparam RF Field type of the range. * \tparam k Maximum polynomial order of the base functions. * * \implements FiniteElementFactoryInterface */ template struct Pk1DFiniteElementFactory { typedef Pk1DFiniteElement FiniteElement; //! construct Pk1DFiniteElementFactory /** * \param geometry The geometry object to use for adaption. * \param vertexOrder The global ordering of the vertices within the grid, * used to determine orientation of the edges. This * vertexOrder object must support codim=0. * * \note The returned object stores the reference to the geometry passed * here. Any use of the returned value after this references has * become invalid results in undefined behaviour. The exception is * that the destructor of this class may still be called. The * information contained in the vertexOrder object is extracted and * the object is no longer needed after the constructor returns. No * reference to internal data of the factory is stored. */ template const FiniteElement make(const Geometry& geometry, const VertexOrder& vertexOrder) { return FiniteElement(geometry, vertexOrder); } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk1d/000077500000000000000000000000001313314431100240625ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk1d/CMakeLists.txt000066400000000000000000000002461313314431100266240ustar00rootroot00000000000000install(FILES pk1dlocalbasis.hh pk1dlocalcoefficients.hh pk1dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/pk1d) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk1d/pk1dlocalbasis.hh000066400000000000000000000100021313314431100272700ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_Pk1DLOCALBASIS_HH #define DUNE_Pk1DLOCALBASIS_HH #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lagrange shape functions of arbitrary order on the 1D reference triangle. Lagrange shape functions of arbitrary order have the property that \f$\hat\phi^i(x_j) = \delta_{i,j}\f$ for certain points \f$x_j\f$. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam k Polynomial order. \nosubgrouping */ template class Pk1DLocalBasis { public: /** \brief Export the number of degrees of freedom */ enum {N = k+1}; /** \brief Export the element order */ enum {O = k}; typedef LocalBasisTraits, R, 1, Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor Pk1DLocalBasis () { for (unsigned int i=0; i<=k; i++) pos[i] = (1.0*i)/std::max(k,(unsigned int)1); } //! \brief number of shape functions unsigned int size () const { return N; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& x, std::vector& out) const { out.resize(N); for (unsigned int i=0; i& out) const // return value { out.resize(N); for (unsigned int i=0; i<=k; i++) { // x_0 derivative out[i][0][0] = 0.0; R factor=1.0; for (unsigned int a=0; a& order, const typename Traits::DomainType& in, std::vector& out) const { switch (order[0]) { case 0: evaluateFunction(in,out); break; default: DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return k; } private: R pos[k+1]; // positions on the interval }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk1d/pk1dlocalcoefficients.hh000066400000000000000000000036231313314431100306430ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PK1DLOCALCOEFFICIENTS_HH #define DUNE_PK1DLOCALCOEFFICIENTS_HH #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for Pk elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class Pk1DLocalCoefficients { enum {N = k+1}; public: //! \brief Standard constructor Pk1DLocalCoefficients () : li(N) { fill_default(); } //! constructor for eight variants with order on edges flipped Pk1DLocalCoefficients (int variant) : li(N) { fill_default(); } /** Constructor for six variants with permuted vertices. \param vertexmap The permutation of the vertices. This can for instance be generated from the global indices of the vertices by reducing those to the integers 0...2. This may be any object which for which the expression \c vertexmap[i] is defined appropriately (like an array, a pointer, a std::vector, or a random-access iterator. */ template explicit Pk1DLocalCoefficients(const VertexMap &vertexmap) : li(N) { fill_default(); } //! number of coefficients std::size_t size () const { return N; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; void fill_default() { li.resize(N); if (N==1) { li[0] = LocalKey(0,0,0); } else { li[0] = LocalKey(0,1,0); for (int i=1; i namespace Dune { template class Pk1DLocalInterpolation { /** \brief The number of degrees of freedom */ enum {N = LB::N}; /** \brief Export the element order */ enum {k = LB::O}; private: static const int kdiv = (k == 0 ? 1 : k); public: template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; typedef typename LB::Traits::DomainFieldType D; out.resize(N); #if DUNE_COMMON_FIELDVECTOR_SIZE_IS_METHOD assert(x.size()==1); #endif for (int i=0; i #include #include #include #include "pk2d/pk2dlocalbasis.hh" #include "pk2d/pk2dlocalcoefficients.hh" #include "pk2d/pk2dlocalinterpolation.hh" namespace Dune { /** \todo Please doc me ! */ template class Pk2DLocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, Pk2DLocalCoefficients, Pk2DLocalInterpolation > > Traits; /** \todo Please doc me ! */ Pk2DLocalFiniteElement () { gt.makeTriangle(); } /** \todo Please doc me ! */ Pk2DLocalFiniteElement (int variant) : coefficients(variant) { gt.makeTriangle(); } /** Constructor for six variants with permuted vertices. \param vertexmap The permutation of the vertices. This can for instance be generated from the global indices of the vertices by reducing those to the integers 0...2 */ Pk2DLocalFiniteElement (const unsigned int vertexmap[3]) : coefficients(vertexmap) { gt.makeTriangle(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } Pk2DLocalFiniteElement* clone () const { return new Pk2DLocalFiniteElement(*this); } private: Pk2DLocalBasis basis; Pk2DLocalCoefficients coefficients; Pk2DLocalInterpolation > interpolation; GeometryType gt; }; //! Langrange finite element of arbitrary order on triangles /** * \tparam Geometry Geometry for the local to global transformation. * \tparam RF Field type of the range. * \tparam k Maximum polynomial order of the base functions. * * \implements FiniteElementInterface */ template class Pk2DFiniteElement { typedef typename Geometry::ctype DF; typedef Pk2DLocalBasis LocalBasis; typedef Pk2DLocalInterpolation LocalInterpolation; public: /** * \implements FiniteElementInterface::Traits */ struct Traits { typedef ScalarLocalToGlobalBasisAdaptor Basis; typedef LocalToGlobalInterpolationAdaptor< LocalInterpolation, typename Basis::Traits > Interpolation; typedef Pk2DLocalCoefficients Coefficients; }; private: static const GeometryType gt; static const LocalBasis localBasis; static const LocalInterpolation localInterpolation; typename Traits::Basis basis_; typename Traits::Interpolation interpolation_; typename Traits::Coefficients coefficients_; public: //! construct a Pk2DFiniteElement /** * \param geometry The geometry object to use for adaption. * \param vertexOrder The global ordering of the vertices within the grid, * used to determine orientation of the edges. This * vertexOrder object must support codim=0. * * \note This class stores the reference to the geometry passed here. Any * use of this class after this references has become invalid * results in undefined behaviour. The exception is that the * destructor of this class may still be called. The information * contained in the vertexOrder object is extracted and the object * is no longer needed after the contructor returns. */ template Pk2DFiniteElement(const Geometry &geometry, const VertexOrder& vertexOrder) : basis_(localBasis, geometry), interpolation_(localInterpolation), coefficients_(vertexOrder.begin(0, 0)) { } const typename Traits::Basis& basis() const { return basis_; } const typename Traits::Interpolation& interpolation() const { return interpolation_; } const typename Traits::Coefficients& coefficients() const { return coefficients_; } const GeometryType &type() const { return gt; } }; template const GeometryType Pk2DFiniteElement::gt(GeometryType::simplex, 2); template const typename Pk2DFiniteElement::LocalBasis Pk2DFiniteElement::localBasis = LocalBasis(); template const typename Pk2DFiniteElement::LocalInterpolation Pk2DFiniteElement::localInterpolation = LocalInterpolation(); //! Factory for Pk2DFiniteElement objects /** * Constructs Pk2DFiniteElement objects given a geometry and a vertex * ordering. * * \tparam Geometry Geometry for the local to global transformation. * \tparam RF Field type of the range. * \tparam k Maximum polynomial order of the base functions. * * \implements FiniteElementFactoryInterface */ template struct Pk2DFiniteElementFactory { typedef Pk2DFiniteElement FiniteElement; //! construct Pk2DFiniteElementFactory /** * \param geometry The geometry object to use for adaption. * \param vertexOrder The global ordering of the vertices within the grid, * used to determine orientation of the edges. This * vertexOrder object must support codim=0. * * \note The returned object stores the reference to the geometry passed * here. Any use of the returned value after this references has * become invalid results in undefined behaviour. The exception is * that the destructor of this class may still be called. The * information contained in the vertexOrder object is extracted and * the object is no longer needed after the contructor returns. No * reference to internal data of the factory is stored. */ template const FiniteElement make(const Geometry& geometry, const VertexOrder& vertexOrder) { return FiniteElement(geometry, vertexOrder); } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk2d/000077500000000000000000000000001313314431100240635ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk2d/CMakeLists.txt000066400000000000000000000002461313314431100266250ustar00rootroot00000000000000install(FILES pk2dlocalbasis.hh pk2dlocalcoefficients.hh pk2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/pk2d) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk2d/pk2dlocalbasis.hh000066400000000000000000000243751313314431100273140ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PK2DLOCALBASIS_HH #define DUNE_PK2DLOCALBASIS_HH #include #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lagrange shape functions of arbitrary order on the reference triangle. Lagrange shape functions of arbitrary order have the property that \f$\hat\phi^i(x_j) = \delta_{i,j}\f$ for certain points \f$x_j\f$. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam k Polynomial order. \nosubgrouping */ template class Pk2DLocalBasis { public: /** \brief Export the number of degrees of freedom */ enum {N = (k+1)*(k+2)/2}; /** \brief Export the element order OS: Surprising that we need to export this both statically and dynamically! */ enum {O = k}; typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix, 2 > Traits; //! \brief Standard constructor Pk2DLocalBasis () { for (unsigned int i=0; i<=k; i++) pos_[i] = (1.0*i)/std::max(k,(unsigned int)1); } //! \brief number of shape functions unsigned int size () const { return N; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& x, std::vector& out) const { out.resize(N); // specialization for k==0, not clear whether that is needed if (k==0) { out[0] = 1; return; } int n=0; for (unsigned int j=0; j<=k; j++) for (unsigned int i=0; i<=k-j; i++) { out[n] = 1.0; for (unsigned int alpha=0; alpha& out) const // return value { out.resize(N); // specialization for k==0, not clear whether that is needed if (k==0) { out[0][0][0] = 0; out[0][0][1] = 0; return; } int n=0; for (unsigned int j=0; j<=k; j++) for (unsigned int i=0; i<=k-j; i++) { // x_0 derivative out[n][0][0] = 0.0; R factor=1.0; for (unsigned int beta=0; beta& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); switch (totalOrder) { case 0: evaluateFunction(in,out); break; case 1: { std::array directions; directions[0] = std::find(order.begin(), order.end(), 1)-order.begin(); DUNE_NO_DEPRECATED_BEGIN evaluate<1>(directions, in, out); DUNE_NO_DEPRECATED_END break; } case 2: { std::array directions; unsigned int counter = 0; auto nonconstOrder = order; // need a copy that I can modify for (int i=0; i<2; i++) { while (nonconstOrder[i]) { directions[counter++] = i; nonconstOrder[i]--; } } DUNE_NO_DEPRECATED_BEGIN evaluate<2>(directions, in, out); DUNE_NO_DEPRECATED_END break; } default: DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Evaluate higher derivatives of all shape functions template //order of derivative inline void DUNE_DEPRECATED_MSG("Use method 'partial' instead!") evaluate(const std::array& directions, //direction of derivative const typename Traits::DomainType& in, //position std::vector& out) const //return value { out.resize(N); if (dOrder > Traits::diffOrder) DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); if (dOrder==0) evaluateFunction(in, out); else if (dOrder==1) { int n=0; for (unsigned int j=0; j<=k; j++) for (unsigned int i=0; i<=k-j; i++, n++) { out[n] = 0.0; for (unsigned int no1=0; no1 < k; no1++) { R factor = lagrangianFactorDerivative(directions[0], no1, i, j, in); for (unsigned int no2=0; no2 < k; no2++) if (no1 != no2) factor *= lagrangianFactor(no2, i, j, in); out[n] += factor; } } } else if (dOrder==2) { // specialization for k<2, not clear whether that is needed if (k<2) { std::fill(out.begin(), out.end(), 0.0); return; } //f = prod_{i} f_i -> dxa dxb f = sum_{i} {dxa f_i sum_{k \neq i} dxb f_k prod_{l \neq k,i} f_l int n=0; for (unsigned int j=0; j<=k; j++) for (unsigned int i=0; i<=k-j; i++, n++) { R res = 0.0; for (unsigned int no1=0; no1 < k; no1++) { R factor1 = lagrangianFactorDerivative(directions[0], no1, i, j, in); for (unsigned int no2=0; no2 < k; no2++) { if (no1 == no2) continue; R factor2 = factor1*lagrangianFactorDerivative(directions[1], no2, i, j, in); for (unsigned int no3=0; no3 < k; no3++) { if (no3 == no1 || no3 == no2) continue; factor2 *= lagrangianFactor(no3, i, j, in); } res += factor2; } } out[n] = res; } } } //! \brief Polynomial order of the shape functions unsigned int order () const { return k; } private: /** \brief Returns a single Lagrangian factor of l_ij evaluated at x */ typename Traits::RangeType lagrangianFactor(const int no, const int i, const int j, const typename Traits::DomainType& x) const { if ( no < i) return (x[0]-pos_[no])/(pos_[i]-pos_[no]); if (no < i+j) return (x[1]-pos_[no-i])/(pos_[j]-pos_[no-i]); return (pos_[no+1]-x[0]-x[1])/(pos_[no+1]-pos_[i]-pos_[j]); } /** \brief Returns the derivative of a single Lagrangian factor of l_ij evaluated at x * \param direction Derive in x-direction if this is 0, otherwise derive in y direction */ typename Traits::RangeType lagrangianFactorDerivative(const int direction, const int no, const int i, const int j, const typename Traits::DomainType& x) const { if ( no < i) return (direction == 0) ? 1.0/(pos_[i]-pos_[no]) : 0; if (no < i+j) return (direction == 0) ? 0: 1.0/(pos_[j]-pos_[no-i]); return -1.0/(pos_[no+1]-pos_[i]-pos_[j]); } D pos_[k+1]; // positions on the interval }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk2d/pk2dlocalcoefficients.hh000066400000000000000000000060521313314431100306440ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PK2DLOCALCOEFFICIENTS_HH #define DUNE_PK2DLOCALCOEFFICIENTS_HH #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for P0 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class Pk2DLocalCoefficients { enum {N = (k+1)*(k+2)/2}; public: //! \brief Standard constructor Pk2DLocalCoefficients () : li(N) { fill_default(); } //! constructor for eight variants with order on edges flipped Pk2DLocalCoefficients (int variant) : li(N) { fill_default(); bool flip[3]; for (int i = 0; i < 3; ++i) flip[i] = variant & (1< explicit Pk2DLocalCoefficients(const VertexMap &vertexmap) : li(N) { fill_default(); bool flip[3]; flip[0] = vertexmap[0] > vertexmap[1]; flip[1] = vertexmap[0] > vertexmap[2]; flip[2] = vertexmap[1] > vertexmap[2]; for (std::size_t i=0; i li; void fill_default () { if (k==0) { li[0] = LocalKey(0,0,0); return; } int n=0; int c=0; for (unsigned int j=0; j<=k; j++) for (unsigned int i=0; i<=k-j; i++) { if (i==0 && j==0) { li[n++] = LocalKey(0,2,0); continue; } if (i==k && j==0) { li[n++] = LocalKey(1,2,0); continue; } if (i==0 && j==k) { li[n++] = LocalKey(2,2,0); continue; } if (j==0) { li[n++] = LocalKey(0,1,i-1); continue; } if (i==0) { li[n++] = LocalKey(1,1,j-1); continue; } if (i+j==k) { li[n++] = LocalKey(2,1,j-1); continue; } li[n++] = LocalKey(0,0,c++); } } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk2d/pk2dlocalinterpolation.hh000066400000000000000000000017301313314431100310700ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_Pk2DLOCALINTERPOLATION_HH #define DUNE_Pk2DLOCALINTERPOLATION_HH #include namespace Dune { template class Pk2DLocalInterpolation { /** \brief The number of degrees of freedom */ enum {N = LB::N}; /** \brief Export the element order */ enum {k = LB::O}; private: static const int kdiv = (k == 0 ? 1 : k); public: template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; typedef typename LB::Traits::DomainFieldType D; out.resize(N); int n=0; for (int j=0; j<=k; j++) for (int i=0; i<=k-j; i++) { x[0] = ((D)i)/((D)kdiv); x[1] = ((D)j)/((D)kdiv); f.evaluate(x,y); out[n] = y; n++; } } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk3d.hh000066400000000000000000000042351313314431100244110ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_Pk3DLOCALFINITEELEMENT_HH #define DUNE_Pk3DLOCALFINITEELEMENT_HH #include #include #include "pk3d/pk3dlocalbasis.hh" #include "pk3d/pk3dlocalcoefficients.hh" #include "pk3d/pk3dlocalinterpolation.hh" namespace Dune { /** \todo Please doc me ! */ template class Pk3DLocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, Pk3DLocalCoefficients, Pk3DLocalInterpolation > > Traits; /** \todo Please doc me ! */ Pk3DLocalFiniteElement () { gt.makeTetrahedron(); } /** Constructor for variants with permuted vertices. \param vertexmap The permutation of the vertices. This can for instance be generated from the global indices of the vertices by reducing those to the integers 0...3 */ Pk3DLocalFiniteElement (const unsigned int vertexmap[4]) : coefficients(vertexmap) { gt.makeTetrahedron(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } Pk3DLocalFiniteElement* clone () const { return new Pk3DLocalFiniteElement(*this); } private: Pk3DLocalBasis basis; Pk3DLocalCoefficients coefficients; Pk3DLocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk3d/000077500000000000000000000000001313314431100240645ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk3d/CMakeLists.txt000066400000000000000000000002461313314431100266260ustar00rootroot00000000000000install(FILES pk3dlocalbasis.hh pk3dlocalcoefficients.hh pk3dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/pk3d) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk3d/pk3dlocalbasis.hh000066400000000000000000000171351313314431100273120ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PK3DLOCALBASIS_HH #define DUNE_PK3DLOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lagrange shape functions of arbitrary order on the reference tetrahedron. Lagrange shape functions of arbitrary order have the property that \f$\hat\phi^i(x_j) = \delta_{i,j}\f$ for certain points \f$x_j\f$. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam k Polynomial order. \nosubgrouping */ template class Pk3DLocalBasis { public: enum {N = (k+1)*(k+2)*(k+3)/6}; enum {O = k}; typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor Pk3DLocalBasis () {} //! \brief number of shape functions unsigned int size () const { return N; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& x, std::vector& out) const { out.resize(N); typename Traits::DomainType kx = x; kx *= k; unsigned int n = 0; unsigned int i[4]; R factor[4]; for (i[2] = 0; i[2] <= k; ++i[2]) { factor[2] = 1.0; for (unsigned int j = 0; j < i[2]; ++j) factor[2] *= (kx[2]-j) / (i[2]-j); for (i[1] = 0; i[1] <= k - i[2]; ++i[1]) { factor[1] = 1.0; for (unsigned int j = 0; j < i[1]; ++j) factor[1] *= (kx[1]-j) / (i[1]-j); for (i[0] = 0; i[0] <= k - i[1] - i[2]; ++i[0]) { factor[0] = 1.0; for (unsigned int j = 0; j < i[0]; ++j) factor[0] *= (kx[0]-j) / (i[0]-j); i[3] = k - i[0] - i[1] - i[2]; D kx3 = k - kx[0] - kx[1] - kx[2]; factor[3] = 1.0; for (unsigned int j = 0; j < i[3]; ++j) factor[3] *= (kx3-j) / (i[3]-j); out[n++] = factor[0] * factor[1] * factor[2] * factor[3]; } } } } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& x, // position std::vector& out) const // return value { out.resize(N); typename Traits::DomainType kx = x; kx *= k; unsigned int n = 0; unsigned int i[4]; R factor[4]; for (i[2] = 0; i[2] <= k; ++i[2]) { factor[2] = 1.0; for (unsigned int j = 0; j < i[2]; ++j) factor[2] *= (kx[2]-j) / (i[2]-j); for (i[1] = 0; i[1] <= k - i[2]; ++i[1]) { factor[1] = 1.0; for (unsigned int j = 0; j < i[1]; ++j) factor[1] *= (kx[1]-j) / (i[1]-j); for (i[0] = 0; i[0] <= k - i[1] - i[2]; ++i[0]) { factor[0] = 1.0; for (unsigned int j = 0; j < i[0]; ++j) factor[0] *= (kx[0]-j) / (i[0]-j); i[3] = k - i[0] - i[1] - i[2]; D kx3 = k - kx[0] - kx[1] - kx[2]; R sum3 = 0.0; factor[3] = 1.0; for (unsigned int j = 0; j < i[3]; ++j) factor[3] /= i[3] - j; R prod_all = factor[0] * factor[1] * factor[2] * factor[3]; for (unsigned int j = 0; j < i[3]; ++j) { R prod = prod_all; for (unsigned int l = 0; l < i[3]; ++l) if (j == l) prod *= -R(k); else prod *= kx3 - l; sum3 += prod; } for (unsigned int j = 0; j < i[3]; ++j) factor[3] *= kx3 - j; for (unsigned int m = 0; m < 3; ++m) { out[n][0][m] = sum3; for (unsigned int j = 0; j < i[m]; ++j) { R prod = factor[3]; for (unsigned int p = 0; p < 3; ++p) { if (m == p) for (unsigned int l = 0; l < i[p]; ++l) if (j == l) prod *= R(k) / (i[p]-l); else prod *= (kx[p]-l) / (i[p]-l); else prod *= factor[p]; } out[n][0][m] += prod; } } n++; } } } } /** \brief Evaluate partial derivatives of any order of all shape functions * \param order Order of the partial derivatives, in the classic multi-index notation * \param in Position where to evaluate the derivatives * \param[out] out Return value: the desired partial derivatives */ void partial(const std::array& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return k; } }; //Specialization for k=0 template class Pk3DLocalBasis { public: typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; /** \brief Export the number of degrees of freedom */ enum {N = 1}; /** \brief Export the element order */ enum {O = 0}; unsigned int size () const { return 1; } inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(1); out[0] = 1; } // evaluate derivative of a single component inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(1); out[0][0][0] = 0; out[0][0][1] = 0; out[0][0][2] = 0; } /** \brief Evaluate partial derivatives of any order of all shape functions * \param order Order of the partial derivatives, in the classic multi-index notation * \param in Position where to evaluate the derivatives * \param[out] out Return value: the desired partial derivatives */ void partial(const std::array& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { out.resize(N); out[0] = 0; } } // local interpolation of a function template void interpolate (const E& e, const F& f, std::vector& out) const { typename Traits::DomainType x; typename Traits::RangeType y; x[0] = 1.0/4.0; x[1] = 1.0/4.0; x[2] = 1.0/4.0; f.eval_local(e,x,y); out[0] = y; } unsigned int order () const { return 0; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk3d/pk3dlocalcoefficients.hh000066400000000000000000000047331313314431100306520ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PK3DLOCALCOEFFICIENTS_HH #define DUNE_PK3DLOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Please doc me! \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class Pk3DLocalCoefficients { enum {N = (k+1)*(k+2)*(k+3)/6}; public: //! \brief Standard constructor Pk3DLocalCoefficients () : li(N) { const unsigned int vertexmap[4] = {0, 1, 2, 3}; generate_local_keys(vertexmap); } /** Constructor for variants with permuted vertices. \param vertexmap The permutation of the vertices. This can for instance be generated from the global indices of the vertices by reducing those to the integers 0...3 */ Pk3DLocalCoefficients (const unsigned int vertexmap[4]) : li(N) { generate_local_keys(vertexmap); } //! number of coefficients std::size_t size () const { return N; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; void generate_local_keys(const unsigned int vertexmap[4]) { unsigned int subindex[16]; unsigned int codim_count[4] = {0}; for (unsigned int m = 1; m < 16; ++m) { unsigned int codim = !(m&1) + !(m&2) + !(m&4) + !(m&8); subindex[m] = codim_count[codim]++; } int a1 = (3*k + 12)*k + 11; int a2 = -3*k - 6; unsigned int dof_count[16] = {0}; unsigned int i[4]; for (i[3] = 0; i[3] <= k; ++i[3]) for (i[2] = 0; i[2] <= k - i[3]; ++i[2]) for (i[1] = 0; i[1] <= k - i[2] - i[3]; ++i[1]) { i[0] = k - i[1] - i[2] - i[3]; unsigned int j[4]; unsigned int entity = 0; unsigned int codim = 0; for (unsigned int m = 0; m < 4; ++m) { j[m] = i[vertexmap[m]]; entity += !!j[m] << m; codim += !j[m]; } int local_index = j[3]*(a1 + (a2 + j[3])*j[3])/6 + j[2]*(2*(k - j[3]) + 3 - j[2])/2 + j[1]; li[local_index] = LocalKey(subindex[entity], codim, dof_count[entity]++); } } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pk3d/pk3dlocalinterpolation.hh000066400000000000000000000017671313314431100311040ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_Pk3DLOCALINTERPOLATION_HH #define DUNE_Pk3DLOCALINTERPOLATION_HH #include namespace Dune { template class Pk3DLocalInterpolation { enum {N = LB::N}; enum {k = LB::O}; private: static const int kdiv = (k == 0 ? 1 : k); public: template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; typedef typename LB::Traits::DomainFieldType D; out.resize(N); int n=0; for (int i2 = 0; i2 <= k; i2++) for (int i1 = 0; i1 <= k-i2; i1++) for (int i0 = 0; i0 <= k-i1-i2; i0++) { x[0] = ((D)i0)/((D)kdiv); x[1] = ((D)i1)/((D)kdiv); x[2] = ((D)i2)/((D)kdiv); f.evaluate(x,y); out[n] = y; n++; } } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pq22d.hh000066400000000000000000000051271313314431100245010ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PQ22DLOCALFINITEELEMENT_HH #define DUNE_PQ22DLOCALFINITEELEMENT_HH #include #include #include #include "qk.hh" #include "pk2d.hh" namespace Dune { template class PQ22DLocalFiniteElement { typedef Dune::FieldVector Domain; typedef Dune::FieldVector Range; typedef LocalBasisTraits, 0 > BasisTraits; typedef typename Dune::LocalFiniteElementVirtualInterface LocalFiniteElementBase; public: typedef LocalFiniteElementTraits< LocalBasisVirtualInterface, LocalCoefficientsVirtualInterface, LocalInterpolationVirtualInterface< Domain, Range > > Traits; typedef typename Traits::LocalBasisType LocalBasis; typedef typename Traits::LocalCoefficientsType LocalCoefficients; typedef typename Traits::LocalInterpolationType LocalInterpolation; PQ22DLocalFiniteElement ( const GeometryType > ) : gt_(gt) { if ( gt.isTriangle() ) setup( Pk2DLocalFiniteElement() ); else if ( gt.isQuadrilateral() ) setup( QkLocalFiniteElement() ); } PQ22DLocalFiniteElement ( const GeometryType >, const std::vector vertexmap ) : gt_(gt) { if ( gt.isTriangle() ) setup( Pk2DLocalFiniteElement(vertexmap) ); else if ( gt.isQuadrilateral() ) setup( QkLocalFiniteElement() ); } PQ22DLocalFiniteElement ( const PQ22DLocalFiniteElement& other ) : gt_(other.gt_) { fe_ = other.fe_->clone(); } ~PQ22DLocalFiniteElement ( ) { delete fe_; } const LocalBasis& localBasis () const { return fe_->localBasis(); } const LocalCoefficients& localCoefficients () const { return fe_->localCoefficients(); } const LocalInterpolation& localInterpolation () const { return fe_->localInterpolation(); } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return fe_->localBasis().size(); } const GeometryType &type () const { return gt_; } private: template void setup(const FE& fe) { fe_ = new LocalFiniteElementVirtualImp(fe); } const GeometryType gt_; const LocalFiniteElementBase *fe_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pqkfactory.hh000066400000000000000000000126231313314431100257330ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PQK_FACTORY_HH #define DUNE_PQK_FACTORY_HH #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { /** \brief Factory that only creates dimension specific local finite elements * * Empty default implementation */ template struct DimSpecificPQkLocalFiniteElementFactory { typedef typename FixedOrderLocalBasisTraits::Traits::LocalBasisType::Traits,0>::Traits T; //! create finite element for given GeometryType static LocalFiniteElementVirtualInterface* create(const GeometryType& gt) { return 0; } }; /** \brief Factory that only creates dimension specific local finite elements * * Specialization for dim=3 */ template struct DimSpecificPQkLocalFiniteElementFactory { typedef typename FixedOrderLocalBasisTraits::Traits::LocalBasisType::Traits,0>::Traits T; typedef PrismP1LocalFiniteElement PrismP1; typedef PrismP2LocalFiniteElement PrismP2; typedef PyramidP1LocalFiniteElement PyramidP1; typedef PyramidP2LocalFiniteElement PyramidP2; //! create finite element for given GeometryType static LocalFiniteElementVirtualInterface* create(const GeometryType& gt) { if ((gt.isPrism())and (k==1)) return new LocalFiniteElementVirtualImp(PrismP1()); if ((gt.isPrism())and (k==2)) return new LocalFiniteElementVirtualImp(PrismP2()); if ((gt.isPyramid())and (k==1)) return new LocalFiniteElementVirtualImp(PyramidP1()); if ((gt.isPyramid())and (k==2)) return new LocalFiniteElementVirtualImp(PyramidP2()); return 0; } }; /** \brief Factory to create any kind of Pk/Qk like element wrapped for the virtual interface * */ template struct PQkLocalFiniteElementFactory { typedef typename FixedOrderLocalBasisTraits::Traits::LocalBasisType::Traits,0>::Traits T; typedef LocalFiniteElementVirtualInterface FiniteElementType; typedef P0LocalFiniteElement P0; typedef PkLocalFiniteElement Pk; typedef QkLocalFiniteElement Qk; //! create finite element for given GeometryType static FiniteElementType* create(const GeometryType& gt) { if (k==0) return new LocalFiniteElementVirtualImp(P0(gt)); if (gt.isSimplex()) return new LocalFiniteElementVirtualImp(Pk()); if (gt.isCube()) return new LocalFiniteElementVirtualImp(Qk()); return DimSpecificPQkLocalFiniteElementFactory::create(gt); } }; /** \brief A cache that stores all available Pk/Qk like local finite elements for the given dimension and order * * An interface for dealing with different vertex orders is currently missing. * So you can in general only use this for order=1,2 or with global DG spaces * * \tparam D Type used for domain coordinates * \tparam R Type used for shape function values * \tparam dim Element dimension * \tparam k Element order */ template class PQkLocalFiniteElementCache { protected: typedef typename FixedOrderLocalBasisTraits::Traits::LocalBasisType::Traits,0>::Traits T; typedef LocalFiniteElementVirtualInterface FE; typedef typename std::map FEMap; public: /** \brief Type of the finite elements stored in this cache */ typedef FE FiniteElementType; /** \brief Default constructor */ PQkLocalFiniteElementCache() {} /** \brief Copy constructor */ PQkLocalFiniteElementCache(const PQkLocalFiniteElementCache& other) { typename FEMap::iterator it = other.cache_.begin(); typename FEMap::iterator end = other.cache_.end(); for(; it!=end; ++it) cache_[it->first] = (it->second)->clone(); } ~PQkLocalFiniteElementCache() { typename FEMap::iterator it = cache_.begin(); typename FEMap::iterator end = cache_.end(); for(; it!=end; ++it) delete it->second; } //! Get local finite element for given GeometryType const FiniteElementType& get(const GeometryType& gt) const { typename FEMap::const_iterator it = cache_.find(gt); if (it==cache_.end()) { FiniteElementType* fe = PQkLocalFiniteElementFactory::create(gt); if (fe==0) DUNE_THROW(Dune::NotImplemented,"No Pk/Qk like local finite element available for geometry type " << gt << " and order " << k); cache_[gt] = fe; return *fe; } return *(it->second); } protected: mutable FEMap cache_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp1.hh000066400000000000000000000035121313314431100251400ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P13DLOCALFINITEELEMENT_HH #define DUNE_P13DLOCALFINITEELEMENT_HH #include #include #include "prismp1/prismp1localbasis.hh" #include "prismp1/prismp1localcoefficients.hh" #include "prismp1/prismp1localinterpolation.hh" namespace Dune { /** \brief First-order Lagrangian finite element on a prism */ template class PrismP1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits,PrismP1LocalCoefficients, PrismP1LocalInterpolation > > Traits; /** \todo Please doc me ! */ PrismP1LocalFiniteElement () { gt.makePrism(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } PrismP1LocalFiniteElement* clone () const { return new PrismP1LocalFiniteElement(*this); } private: PrismP1LocalBasis basis; PrismP1LocalCoefficients coefficients; PrismP1LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp1/000077500000000000000000000000001313314431100246165ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp1/CMakeLists.txt000066400000000000000000000002621313314431100273560ustar00rootroot00000000000000install(FILES prismp1localbasis.hh prismp1localcoefficients.hh prismp1localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/prismp1) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp1/prismp1localbasis.hh000066400000000000000000000105511313314431100305710ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PRISM_P1_LOCALBASIS_HH #define DUNE_PRISM_P1_LOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Linear Lagrange shape functions on the prism. Defines the linear shape functions on the prism. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class PrismP1LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 6; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(6); out[0] = (1.0-in[0]-in[1])*(1.0-in[2]); out[1] = in[0]*(1-in[2]); out[2] = in[1]*(1-in[2]); out[3] = in[2]*(1.0-in[0]-in[1]); out[4] = in[0]*in[2]; out[5] = in[1]*in[2]; } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(6); out[0][0][0] = in[2]-1; out[0][0][1] = in[2]-1; out[0][0][2] = in[0]+in[1]-1; // basis function 0 out[1][0][0] = 1-in[2]; out[1][0][1] = 0; out[1][0][2] = -in[0]; // basis function 1 out[2][0][0] = 0; out[2][0][1] = 1-in[2]; out[2][0][2] = -in[1]; // basis function 2 out[3][0][0] = -in[2]; out[3][0][1] = -in[2]; out[3][0][2] = 1-in[0]-in[1]; // basis function 3 out[4][0][0] = in[2]; out[4][0][1] = 0; out[4][0][2] = in[0]; // basis function 4 out[5][0][0] = 0; out[5][0][1] = in[2]; out[5][0][2] = in[1]; // basis function 5 } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { auto direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); switch (direction) { case 0: out[0] = in[2]-1; out[1] = 1-in[2]; out[2] = 0; out[3] = -in[2]; out[4] = in[2]; out[5] = 0; break; case 1: out[0] = in[2]-1; out[1] = 0; out[2] = 1-in[2]; out[3] = -in[2]; out[4] = 0; out[5] = in[2]; break; case 2: out[0] = in[0]+in[1]-1; out[1] = -in[0]; out[2] = -in[1]; out[3] = 1-in[0]-in[1]; out[4] = in[0]; out[5] = in[1]; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else if (totalOrder == 2) { out.resize(size()); if (order[0] == 1 && order[2] == 1) { out[0] = 1; out[1] =-1; out[2] = 0; out[3] =-1; out[4] = 1; out[5] = 0; } else if (order[1] == 1 && order[2] == 1) { out[0] = 1; out[1] = 0; out[2] =-1; out[3] =-1; out[4] = 0; out[5] = 1; } else { for (std::size_t i = 0; i < size(); ++i) out[i] = 0; } } else { out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i] = 0; } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 1; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp1/prismp1localcoefficients.hh000066400000000000000000000016521313314431100321330ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PRISMP1LOCALCOEFFICIENTS_HH #define DUNE_PRISMP1LOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for PrismP1 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class PrismP1LocalCoefficients { public: //! \brief Standard constructor PrismP1LocalCoefficients () : li(6) { for (std::size_t i=0; i<6; i++) li[i] = LocalKey(i,3,0); } //! number of coefficients std::size_t size () const { return 6; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp1/prismp1localinterpolation.hh000066400000000000000000000022111313314431100323510ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PRISM_P1_LOCALINTERPOLATION_HH #define DUNE_PRISM_P1_LOCALINTERPOLATION_HH #include namespace Dune { template class PrismP1LocalInterpolation { public: PrismP1LocalInterpolation () { x[0][0] = 0.0; x[0][1] = 0.0; x[0][2] = 0.0; x[1][0] = 1.0; x[1][1] = 0.0; x[1][2] = 0.0; x[2][0] = 0.0; x[2][1] = 1.0; x[2][2] = 0.0; x[3][0] = 0.0; x[3][1] = 0.0; x[3][2] = 1.0; x[4][0] = 1.0; x[4][1] = 0.0; x[4][2] = 1.0; x[5][0] = 0.0; x[5][1] = 1.0; x[5][2] = 1.0; } //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; out.resize(6); f.evaluate(x[0],y); out[0] = y; f.evaluate(x[1],y); out[1] = y; f.evaluate(x[2],y); out[2] = y; f.evaluate(x[3],y); out[3] = y; f.evaluate(x[4],y); out[4] = y; f.evaluate(x[5],y); out[5] = y; } private: typename LB::Traits::DomainType x[6]; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp2.hh000066400000000000000000000034711313314431100251450ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PRISM2_3DLOCALFINITEELEMENT_HH #define DUNE_PRISM2_3DLOCALFINITEELEMENT_HH #include #include #include "prismp2/prismp2localbasis.hh" #include "prismp2/prismp2localcoefficients.hh" #include "prismp2/prismp2localinterpolation.hh" namespace Dune { /** \todo Please doc me ! */ template class PrismP2LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, PrismP2LocalCoefficients, PrismP2LocalInterpolation > > Traits; /** \todo Please doc me ! */ PrismP2LocalFiniteElement () { gt.makePrism(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } PrismP2LocalFiniteElement* clone () const { return new PrismP2LocalFiniteElement(*this); } private: PrismP2LocalBasis basis; PrismP2LocalCoefficients coefficients; PrismP2LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp2/000077500000000000000000000000001313314431100246175ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp2/CMakeLists.txt000066400000000000000000000002621313314431100273570ustar00rootroot00000000000000install(FILES prismp2localbasis.hh prismp2localcoefficients.hh prismp2localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/prismp2) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp2/prismp2localbasis.hh000066400000000000000000000540571313314431100306040ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PRISM_P2_LOCALBASIS_HH #define DUNE_PRISM_P2_LOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Quadratic Lagrange shape functions on the prism. Defines the quadratic shape functions on prism. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class PrismP2LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 18; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(18); int coeff; R a[2], b[2], c[2], a1d, b1d, c1d; // lower triangle: coeff= 2; a[0] = 1; a[1] = 0.5; b[0] = -1; b[1] = -1; c[0] = -1; c[1] = -1; a1d = 1; b1d = -3; c1d = 2; out[0] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 1; b[1] = 0; c[0] = 1; c[1] = 0; a1d = 1; b1d = -3; c1d = 2; out[1] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 0; b[1] = 1; c[0] = 0; c[1] = 1; a1d = 1; b1d = -3; c1d = 2; out[2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); //upper triangle coeff= 2; a[0] = 1; a[1] = 0.5; b[0] = -1; b[1] = -1; c[0] = -1; c[1] = -1; a1d = 0; b1d = -1; c1d = 2; out[3] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 1; b[1] = 0; c[0] = 1; c[1] = 0; a1d = 0; b1d = -1; c1d = 2; out[4] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 0; b[1] = 1; c[0] = 0; c[1] = 1; a1d = 0; b1d = -1; c1d = 2; out[5] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); // vertical edges coeff= 2; a[0] = 1; a[1] = 0.5; b[0] = -1; b[1] = -1; c[0] = -1; c[1] = -1; a1d = 0; b1d = 4; c1d = -4; out[6] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 1; b[1] = 0; c[0] = 1; c[1] = 0; a1d = 0; b1d = 4; c1d = -4; out[7] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 0; b[1] = 1; c[0] = 0; c[1] = 1; a1d = 0; b1d = 4; c1d = -4; out[8] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); // lower triangle edges coeff= 4; a[0] = 0; a[1] = 1; b[0] = 1; b[1] = 0; c[0] = -1; c[1] = -1; a1d = 1; b1d = -3; c1d = 2; out[9] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 4; a[0] = 0; a[1] = 1; b[0] = 0; b[1] = 1; c[0] = -1; c[1] = -1; a1d = 1; b1d = -3; c1d = 2; out[10] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 4; a[0] = 0; a[1] = 0; b[0] = 1; b[1] = 0; c[0] = 0; c[1] = 1; a1d = 1; b1d = -3; c1d = 2; out[11] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); // upper triangle edges coeff= 4; a[0] = 0; a[1] = 1; b[0] = 1; b[1] = 0; c[0] = -1; c[1] = -1; a1d = 0; b1d = -1; c1d = 2; out[12] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 4; a[0] = 0; a[1] = 1; b[0] = 0; b[1] = 1; c[0] = -1; c[1] = -1; a1d = 0; b1d = -1; c1d = 2; out[13] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 4; a[0] = 0; a[1] = 0; b[0] = 1; b[1] = 0; c[0] = 0; c[1] = 1; a1d = 0; b1d = -1; c1d = 2; out[14] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); // quadrilateral sides coeff= 4; a[0] = 0; a[1] = 1; b[0] = 1; b[1] = 0; c[0] = -1; c[1] = -1; a1d = 0; b1d = 4; c1d = -4; out[15] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 4; a[0] = 0; a[1] = 1; b[0] = 0; b[1] = 1; c[0] = -1; c[1] = -1; a1d = 0; b1d = 4; c1d = -4; out[16] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); coeff= 4; a[0] = 0; a[1] = 0; b[0] = 1; b[1] = 0; c[0] = 0; c[1] = 1; a1d = 0; b1d = 4; c1d = -4; out[17] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1])*(a1d + in[2]*b1d + in[2]*in[2]*c1d); } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(18); int coeff; R a[2], b[2], c[2], aa[2], bb[2][2], a1d, b1d, c1d; // lower triangle: coeff= 2; a[0] = 1; a[1] = 0.5; b[0] = -1; b[1] = -1; c[0] = -1; c[1] = -1; a1d = 1; b1d = -3; c1d = 2; aa[0] = -3; aa[1] = -3; bb[0][0] = 4; bb[0][1] = 4; bb[1][0] = 4; bb[1][1] = 4; out[0][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[0][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[0][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 1; b[1] = 0; c[0] = 1; c[1] = 0; a1d = 1; b1d = -3; c1d = 2; aa[0] = -1; aa[1] = 0; bb[0][0] = 4; bb[0][1] = 0; bb[1][0] = 0; bb[1][1] = 0; out[1][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[1][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[1][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 0; b[1] = 1; c[0] = 0; c[1] = 1; a1d = 1; b1d = -3; c1d = 2; aa[0] = 0; aa[1] = -1; bb[0][0] = 0; bb[0][1] = 0; bb[1][0] = 0; bb[1][1] = 4; out[2][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[2][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[2][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); //upper triangle coeff= 2; a[0] = 1; a[1] = 0.5; b[0] = -1; b[1] = -1; c[0] = -1; c[1] = -1; a1d = 0; b1d = -1; c1d = 2; aa[0] = -3; aa[1] = -3; bb[0][0] = 4; bb[0][1] = 4; bb[1][0] = 4; bb[1][1] = 4; out[3][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[3][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[3][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 1; b[1] = 0; c[0] = 1; c[1] = 0; a1d = 0; b1d = -1; c1d = 2; aa[0] = -1; aa[1] = 0; bb[0][0] = 4; bb[0][1] = 0; bb[1][0] = 0; bb[1][1] = 0; out[4][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[4][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[4][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 0; b[1] = 1; c[0] = 0; c[1] = 1; a1d = 0; b1d = -1; c1d = 2; aa[0] = 0; aa[1] = -1; bb[0][0] = 0; bb[0][1] = 0; bb[1][0] = 0; bb[1][1] = 4; out[5][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[5][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[5][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); // vertical edges coeff= 2; a[0] = 1; a[1] = 0.5; b[0] = -1; b[1] = -1; c[0] = -1; c[1] = -1; a1d = 0; b1d = 4; c1d = -4; aa[0] = -3; aa[1] = -3; bb[0][0] = 4; bb[0][1] = 4; bb[1][0] = 4; bb[1][1] = 4; out[6][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[6][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[6][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 1; b[1] = 0; c[0] = 1; c[1] = 0; a1d = 0; b1d = 4; c1d = -4; aa[0] = -1; aa[1] = 0; bb[0][0] = 4; bb[0][1] = 0; bb[1][0] = 0; bb[1][1] = 0; out[7][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[7][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[7][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 2; a[0] = 0; a[1] = -0.5; b[0] = 0; b[1] = 1; c[0] = 0; c[1] = 1; a1d = 0; b1d = 4; c1d = -4; aa[0] = 0; aa[1] = -1; bb[0][0] = 0; bb[0][1] = 0; bb[1][0] = 0; bb[1][1] = 4; out[8][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[8][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[8][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); // lower triangle edges coeff= 4; a[0] = 0; a[1] = 1; b[0] = 1; b[1] = 0; c[0] = -1; c[1] = -1; a1d = 1; b1d = -3; c1d = 2; aa[0] = 4; aa[1] = 0; bb[0][0] = -8; bb[0][1] = -4; bb[1][0] = -4; bb[1][1] = 0; out[9][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[9][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[9][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 4; a[0] = 0; a[1] = 1; b[0] = 0; b[1] = 1; c[0] = -1; c[1] = -1; a1d = 1; b1d = -3; c1d = 2; aa[0] = 0; aa[1] = 4; //changed from zero to 4 bb[0][0] = 0; bb[0][1] = -4; bb[1][0] = -4; bb[1][1] = -8; out[10][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[10][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[10][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 4; a[0] = 0; a[1] = 0; b[0] = 1; b[1] = 0; c[0] = 0; c[1] = 1; a1d = 1; b1d = -3; c1d = 2; aa[0] = 0; aa[1] = 0; bb[0][0] = 0; bb[0][1] = 4; bb[1][0] = 4; bb[1][1] = 0; out[11][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[11][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[11][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); // upper triangle edges coeff= 4; a[0] = 0; a[1] = 1; b[0] = 1; b[1] = 0; c[0] = -1; c[1] = -1; a1d = 0; b1d = -1; c1d = 2; aa[0] = 4; aa[1] = 0; bb[0][0] = -8; bb[0][1] = -4; bb[1][0] = -4; bb[1][1] = 0; out[12][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[12][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[12][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 4; a[0] = 0; a[1] = 1; b[0] = 0; b[1] = 1; c[0] = -1; c[1] = -1; a1d = 0; b1d = -1; c1d = 2; aa[0] = 0; aa[1] = 4; bb[0][0] = 0; bb[0][1] = -4; bb[1][0] = -4; bb[1][1] = -8; out[13][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[13][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[13][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 4; a[0] = 0; a[1] = 0; b[0] = 1; b[1] = 0; c[0] = 0; c[1] = 1; a1d = 0; b1d = -1; c1d = 2; aa[0] = 0; aa[1] = 0; bb[0][0] = 0; bb[0][1] = 4; bb[1][0] = 4; bb[1][1] = 0; out[14][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[14][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[14][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); // quadrilateral sides coeff= 4; a[0] = 0; a[1] = 1; b[0] = 1; b[1] = 0; c[0] = -1; c[1] = -1; a1d = 0; b1d = 4; c1d = -4; aa[0] = 4; aa[1] = 0; bb[0][0] = -8; bb[0][1] = -4; bb[1][0] = -4; bb[1][1] = 0; out[15][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[15][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[15][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 4; a[0] = 0; a[1] = 1; b[0] = 0; b[1] = 1; c[0] = -1; c[1] = -1; a1d = 0; b1d = 4; c1d = -4; aa[0] = 0; aa[1] = 4; bb[0][0] = 0; bb[0][1] = -4; bb[1][0] = -4; bb[1][1] = -8; out[16][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[16][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[16][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); coeff= 4; a[0] = 0; a[1] = 0; b[0] = 1; b[1] = 0; c[0] = 0; c[1] = 1; a1d = 0; b1d = 4; c1d = -4; aa[0] = 0; aa[1] = 0; bb[0][0] = 0; bb[0][1] = 4; bb[1][0] = 4; bb[1][1] = 0; out[17][0][0] = (aa[0] + bb[0][0]*in[0] + bb[1][0]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[17][0][1] = (aa[1] + bb[0][1]*in[0] + bb[1][1]*in[1]) * (a1d + in[2]*b1d + in[2]*in[2]*c1d); out[17][0][2] = coeff * (a[0] + b[0]*in[0] + b[1]*in[1]) * (a[1] + c[0]*in[0] + c[1]*in[1]) * (b1d + 2*c1d*in[2]); } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: out[0] = (-3 + 4*(in[0] + in[1])) * (1 - 3*in[2] + 2*in[2]*in[2]); out[1] = (-1 + 4*in[0]) * (1 - 3*in[2] + 2*in[2]*in[2]); out[2] = 0; out[3] = (-3 + 4*(in[0] + in[1])) * (-in[2] + 2*in[2]*in[2]); out[4] = (-1 + 4*in[0]) * (-in[2] + 2*in[2]*in[2]); out[5] = 0; out[6] = (-3 + 4*(in[0] + in[1])) * 4*(in[2] - in[2]*in[2]); out[7] = (-1 + 4*in[0]) * 4*(in[2] - in[2]*in[2]); out[8] = 0; out[9] = (4 - 8*in[0] - 4*in[1]) * (1 - 3*in[2] + 2*in[2]*in[2]); out[10] = -4*in[1] * (1 - 3*in[2] + 2*in[2]*in[2]); out[11] = 4*in[1] * (1 - 3*in[2] + 2*in[2]*in[2]); out[12] = (4 - 8*in[0] - 4*in[1]) * (-in[2] + 2*in[2]*in[2]); out[13] = -4*in[1] * (-in[2] + 2*in[2]*in[2]); out[14] = 4*in[1] * (-in[2] + 2*in[2]*in[2]); out[15] = (4 - 8*in[0] - 4*in[1]) * (4*in[2] - 4*in[2]*in[2]); out[16] = -4*in[1] * (4*in[2] - 4*in[2]*in[2]); out[17] = 4*in[1] * (4*in[2] - 4*in[2]*in[2]); break; case 1: out[0] = (-3 + 4*(in[0] + in[1])) * (1 - 3*in[2] + 2*in[2]*in[2]); out[1] = 0; out[2] = (-1 + 4*in[1]) * (1 - 3*in[2] + 2*in[2]*in[2]); out[3] = (-3 + 4*(in[0] + in[1])) * (-in[2] + 2*in[2]*in[2]); out[4] = 0; out[5] = (-1 + 4*in[1]) * (-in[2] + 2*in[2]*in[2]); out[6] = (-3 + 4*(in[0] + in[1])) * 4*(in[2] - in[2]*in[2]); out[7] = 0; out[8] = (-1 + 4*in[1]) * 4*(in[2] - in[2]*in[2]); out[9] = -4*in[0] * (1 - 3*in[2] + 2*in[2]*in[2]); out[10] = (4 - 4*in[0] - 8*in[1]) * (1 - 3*in[2] + 2*in[2]*in[2]); out[11] = 4*in[0] * (1 - 3*in[2] + 2*in[2]*in[2]); out[12] = -4*in[0] * (-in[2] + 2*in[2]*in[2]); out[13] = (4 - 4*in[0] - 8*in[1]) * (-in[2] + 2*in[2]*in[2]); out[14] = 4*in[0] * (-in[2] + 2*in[2]*in[2]); out[15] = -4*in[0] * 4*(in[2] - in[2]*in[2]); out[16] = (4 - 4*in[0] - 8*in[1]) * (4*in[2] - 4*in[2]*in[2]); out[17] = 4*in[0] * (4*in[2] - 4*in[2]*in[2]); break; case 2: out[0] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]) * (-3 + 4*in[2]); out[1] = 2 * in[0] * (-0.5 + in[0]) * (-3 + 4*in[2]); out[2] = 2 * in[1] * (-0.5 + in[1]) * (-3 + 4*in[2]); out[3] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]) * (-1 + 4*in[2]); out[4] = 2 * in[0] * (-0.5 + in[0]) * (-1 + 4*in[2]); out[5] = 2 * in[1] * (-0.5 + in[1]) * (-1 + 4*in[2]); out[6] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]) * (4 - 8*in[2]); out[7] = 2 * in[0] * (-0.5 + in[0]) * (4 - 8*in[2]); out[8] = 2*in[1] * (-0.5 + in[1]) * (4 - 8*in[2]); out[9] = 4*in[0] * (1 - in[0] - in[1]) * (-3 + 4*in[2]); out[10] = 4*in[1] * (1 - in[0] - in[1]) * (-3 + 4*in[2]); out[11] = 4*in[0]*in[1] * (-3 + 4*in[2]); out[12] = 4 * in[0] * (1 - in[0] - in[1]) * (-1 + 4*in[2]); out[13] = 4 * in[1] * (1 - in[0] - in[1]) * (-1 + 4*in[2]); out[14] = 4*in[0]*in[1] * (-1 + 4*in[2]); out[15] = 4 * in[0] * (1 - in[0] - in[1]) * (4 - 8*in[2]); out[16] = 4 * in[1] * (1 - in[0] - in[1]) * (4 - 8*in[2]); out[17] = 4*in[0]*in[1] * (4 - 8*in[2]); break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 2; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp2/prismp2localcoefficients.hh000066400000000000000000000027701313314431100321370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PRISM_P2_LOCALCOEFFICIENTS_HH #define DUNE_PRISM_P2_LOCALCOEFFICIENTS_HH #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for PrismP2 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class PrismP2LocalCoefficients { public: //! \brief Standard constructor PrismP2LocalCoefficients () : li(18) { // Vertex shape functions li[0] = LocalKey(0,3,0); li[1] = LocalKey(1,3,0); li[2] = LocalKey(2,3,0); li[3] = LocalKey(3,3,0); li[4] = LocalKey(4,3,0); li[5] = LocalKey(5,3,0); // Edge shape functions li[6] = LocalKey(0,2,0); li[7] = LocalKey(1,2,0); li[8] = LocalKey(2,2,0); li[9] = LocalKey(3,2,0); li[10] = LocalKey(4,2,0); li[11] = LocalKey(5,2,0); li[12] = LocalKey(6,2,0); li[13] = LocalKey(7,2,0); li[14] = LocalKey(8,2,0); // Quadrilateral sides shape functions li[15] = LocalKey(0,1,0); li[16] = LocalKey(1,1,0); li[17] = LocalKey(2,1,0); } //! number of coefficients std::size_t size () const { return 18; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/prismp2/prismp2localinterpolation.hh000066400000000000000000000040051313314431100323560ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PRISM_P2_LOCALINTERPOLATION_HH #define DUNE_PRISM_P2_LOCALINTERPOLATION_HH #include namespace Dune { template class PrismP2LocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; out.resize(18); typename LB::Traits::DomainType x; x[0] = 0.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[0] = y; x[0] = 1.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[1] = y; x[0] = 0.0; x[1] = 1.0; x[2] = 0.0; f.evaluate(x,y); out[2] = y; x[0] = 0.0; x[1] = 0.0; x[2] = 1.0; f.evaluate(x,y); out[3] = y; x[0] = 1.0; x[1] = 0.0; x[2] = 1.0; f.evaluate(x,y); out[4] = y; x[0] = 0.0; x[1] = 1.0; x[2] = 1.0; f.evaluate(x,y); out[5] = y; x[0] = 0.0; x[1] = 0.0; x[2] = 0.5; f.evaluate(x,y); out[6] = y; x[0] = 1.0; x[1] = 0.0; x[2] = 0.5; f.evaluate(x,y); out[7] = y; x[0] = 0; x[1] = 1.0; x[2] = 0.5; f.evaluate(x,y); out[8] = y; x[0] = 0.5; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[9] = y; x[0] = 0.0; x[1] = 0.5; x[2] = 0.0; f.evaluate(x,y); out[10] = y; x[0] = 0.5; x[1] = 0.5; x[2] = 0.0; f.evaluate(x,y); out[11] = y; x[0] = 0.5; x[1] = 0.0; x[2] = 1.0; f.evaluate(x,y); out[12] = y; x[0] = 0.0; x[1] = 0.5; x[2] = 1.0; f.evaluate(x,y); out[13] = y; x[0] = 0.5; x[1] = 0.5; x[2] = 1.0; f.evaluate(x,y); out[14] = y; x[0] = 0.5; x[1] = 0.0; x[2] = 0.5; f.evaluate(x,y); out[15] = y; x[0] = 0.0; x[1] = 0.5; x[2] = 0.5; f.evaluate(x,y); out[16] = y; x[0] = 0.5; x[1] = 0.5; x[2] = 0.5; f.evaluate(x,y); out[17] = y; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp1.hh000066400000000000000000000036011313314431100254520ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYRAMID_P1_LOCALFINITEELEMENT_HH #define DUNE_PYRAMID_P1_LOCALFINITEELEMENT_HH #include #include #include "pyramidp1/pyramidp1localbasis.hh" #include "pyramidp1/pyramidp1localcoefficients.hh" #include "pyramidp1/pyramidp1localinterpolation.hh" namespace Dune { /** \brief First-order Lagrangian finite element on a prism */ template class PyramidP1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits,PyramidP1LocalCoefficients, PyramidP1LocalInterpolation > > Traits; /** \todo Please doc me ! */ PyramidP1LocalFiniteElement () { gt.makePyramid(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } PyramidP1LocalFiniteElement* clone () const { return new PyramidP1LocalFiniteElement(*this); } private: PyramidP1LocalBasis basis; PyramidP1LocalCoefficients coefficients; PyramidP1LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp1/000077500000000000000000000000001313314431100251315ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp1/CMakeLists.txt000066400000000000000000000002721313314431100276720ustar00rootroot00000000000000install(FILES pyramidp1localbasis.hh pyramidp1localcoefficients.hh pyramidp1localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/pyramidp1) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp1/pyramidp1localbasis.hh000066400000000000000000000132741313314431100314240ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYRAMID_P1_LOCALBASIS_HH #define DUNE_PYRAMID_P1_LOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Linear Lagrange shape functions on the pyramid. Defines the linear shape functions on pyramid. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class PyramidP1LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 5; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(5); if(in[0] > in[1]) { out[0] = (1-in[0])*(1-in[1])-in[2]*(1-in[1]); out[1] = in[0]*(1-in[1])-in[2]*in[1]; out[2] = (1-in[0])*in[1]-in[2]*in[1]; out[3] = in[0]*in[1]+in[2]*in[1]; } else { out[0] = (1-in[0])*(1-in[1])-in[2]*(1-in[0]); out[1] = in[0]*(1-in[1])-in[2]*in[0]; out[2] = (1-in[0])*in[1]-in[2]*in[0]; out[3] = in[0]*in[1]+in[2]*in[0]; } out[4] = in[2]; } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(5); if(in[0] > in[1]) { out[0][0][0] = -1 + in[1]; out[0][0][1] = -1 + in[0] + in[2]; out[0][0][2] = -1 + in[1]; out[1][0][0] = 1 - in[1]; out[1][0][1] = -in[0] - in[2]; out[1][0][2] = -in[1]; out[2][0][0] = -in[1]; out[2][0][1] = 1 - in[0] - in[2]; out[2][0][2] = -in[1]; out[3][0][0] = in[1]; out[3][0][1] = in[0]+in[2]; out[3][0][2] = in[1]; } else { out[0][0][0] = -1 + in[1] + in[2]; out[0][0][1] = -1 + in[0]; out[0][0][2] = -1 + in[0]; out[1][0][0] = 1 - in[1] - in[2]; out[1][0][1] = -in[0]; out[1][0][2] = -in[0]; out[2][0][0] = -in[1] - in[2]; out[2][0][1] = 1 - in[0]; out[2][0][2] = -in[0]; out[3][0][0] = in[1] + in[2]; out[3][0][1] = in[0]; out[3][0][2] = in[0]; } out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 1; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); if (in[0] > in[1]) { switch (direction) { case 0: out[0] = -1 + in[1]; out[1] = 1 - in[1]; out[2] = -in[1]; out[3] = in[1]; out[4] = 0; break; case 1: out[0] = -1 + in[0] + in[2]; out[1] = -in[0] - in[2]; out[2] = 1 - in[0] - in[2]; out[3] = in[0]+in[2]; out[4] = 0; break; case 2: out[0] = -1 + in[1]; out[1] = -in[1]; out[2] = -in[1]; out[3] = in[1]; out[4] = 1; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else /* (in[0] <= in[1]) */ { switch (direction) { case 0: out[0] = -1 + in[1] + in[2]; out[1] = 1 - in[1] - in[2]; out[2] = -in[1] - in[2]; out[3] = in[1] + in[2]; out[4] = 0; break; case 1: out[0] = -1 + in[0]; out[1] = -in[0]; out[2] = 1 - in[0]; out[3] = in[0]; out[4] = 0; break; case 2: out[0] = -1 + in[0]; out[1] = -in[0]; out[2] = -in[0]; out[3] = in[0]; out[4] = 1; break; default: DUNE_THROW(RangeError, "Component out of range."); } } } else if (totalOrder == 2) { out.resize(size()); if ((order[0] == 1 && order[1] == 1) || (order[1] == 1 && order[2] == 1 && in[0] > in[1]) || (order[0] == 1 && order[2] == 1 && in[0] <=in[1])) { out[0] = 1; out[1] =-1; out[2] =-1; out[3] = 1; out[4] = 0; } else { for (std::size_t i = 0; i < size(); ++i) out[i] = 0; } } else { out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i] = 0; } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 1; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp1/pyramidp1localcoefficients.hh000066400000000000000000000016051313314431100327570ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYRAMID_P1_LOCALCOEFFICIENTS_HH #define DUNE_PYRAMID_P1_LOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for PyramidP1 elements \nosubgrouping */ class PyramidP1LocalCoefficients { public: //! \brief Standard constructor PyramidP1LocalCoefficients () : li(5) { for (std::size_t i=0; i<5; i++) li[i] = LocalKey(i,3,0); } //! number of coefficients std::size_t size () const { return 5; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp1/pyramidp1localinterpolation.hh000066400000000000000000000020711313314431100332030ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYRAMID_P1_LOCALINTERPOLATION_HH #define DUNE_PYRAMID_P1_LOCALINTERPOLATION_HH #include namespace Dune { template class PyramidP1LocalInterpolation { public: PyramidP1LocalInterpolation () { x[0][0] = 0.0; x[0][1] = 0.0; x[0][2] = 0.0; x[1][0] = 1.0; x[1][1] = 0.0; x[1][2] = 0.0; x[2][0] = 0.0; x[2][1] = 1.0; x[2][2] = 0.0; x[3][0] = 1.0; x[3][1] = 1.0; x[3][2] = 0.0; x[4][0] = 0.0; x[4][1] = 0.0; x[4][2] = 1.0; } //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; out.resize(5); f.evaluate(x[0],y); out[0] = y; f.evaluate(x[1],y); out[1] = y; f.evaluate(x[2],y); out[2] = y; f.evaluate(x[3],y); out[3] = y; f.evaluate(x[4],y); out[4] = y; } private: typename LB::Traits::DomainType x[5]; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp2.hh000066400000000000000000000035451313314431100254620ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYRAMIDP2_3DLOCALFINITEELEMENT_HH #define DUNE_PYRAMIDP2_3DLOCALFINITEELEMENT_HH #include #include #include "pyramidp2/pyramidp2localbasis.hh" #include "pyramidp2/pyramidp2localcoefficients.hh" #include "pyramidp2/pyramidp2localinterpolation.hh" namespace Dune { /** \todo Please doc me ! */ template class PyramidP2LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, PyramidP2LocalCoefficients, PyramidP2LocalInterpolation > > Traits; /** \todo Please doc me ! */ PyramidP2LocalFiniteElement () { gt.makePyramid(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } PyramidP2LocalFiniteElement* clone () const { return new PyramidP2LocalFiniteElement(*this); } private: PyramidP2LocalBasis basis; PyramidP2LocalCoefficients coefficients; PyramidP2LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp2/000077500000000000000000000000001313314431100251325ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp2/CMakeLists.txt000066400000000000000000000002721313314431100276730ustar00rootroot00000000000000install(FILES pyramidp2localbasis.hh pyramidp2localcoefficients.hh pyramidp2localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/pyramidp2) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp2/pyramidp2localbasis.hh000066400000000000000000000473611313314431100314320ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYRAMID_P2_LOCALBASIS_HH #define DUNE_PYRAMID_P2_LOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Quadratic Lagrange shape functions on the pyramid. Defines the quadratic shape functions on pyramid. Taken from Liping Liu, Kevin B. Davies, Michal Krizek, and Li Guan: On Higher Order Pyramidal Finite Elements Adv. Appl. Math. Mech., Vol. 3, No. 2, pp. 131-140, 2011 \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class PyramidP2LocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 14; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(14); // transform to reference element with base [-1,1]^2 const R x = 2.0*in[0] + in[2] - 1.0; const R y = 2.0*in[1] + in[2] - 1.0; const R z = in[2]; if (x > y) { // vertices out[0] = 0.25*(x + z)*(x + z - 1)*(y - z - 1)*(y - z); out[1] = -0.25*(x + z)*(y - z)*((x + z + 1)*(-y + z + 1) - 4*z) - z*(x - y); out[2] = 0.25*(x + z)*(y - z)*(y - z + 1)*(x + z - 1); out[3] = 0.25*(y - z)*(x + z)*(y - z + 1)*(x + z + 1); out[4] = z*(2*z - 1); // lower edges out[5] = -0.5*(y - z + 1)*(x + z - 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)); out[6] = -0.5*(y - z + 1)*(((x + z + 1)*(y - 1)*x - z) + z*(2*y + 1)); out[7] = -0.5*(x + z - 1)*(((y - z - 1)*(x + 1)*y - z) + z*(2*x + 1)); out[8] = -0.5*(y - z + 1)*(x + z - 1)*(x + 1)*y; // upper edges out[9] = z*(x + z - 1)*(y - z - 1); out[10] = -z*((x + z + 1)*(y - z - 1) + 4*z); out[11] = -z*(y - z + 1)*(x + z - 1); out[12] = z*(y - z + 1)*(x + z + 1); // base face out[13] = (y - z + 1)*(x + z - 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)); } else { // vertices out[0] = 0.25*(y + z)*(y + z - 1)*(x - z - 1)*(x - z); out[1] = -0.25*(x - z)*(y + z)*(x - z + 1)*(-y - z + 1); out[2] = 0.25*(x - z)*(y + z)*((x - z - 1)*(y + z + 1) + 4*z) + z*(x - y); out[3] = 0.25*(y + z)*(x - z)*(x - z + 1)*(y + z + 1); out[4] = z*(2*z - 1); // lower edges out[5] = -0.5*(y + z - 1)*(((x - z - 1)*(y + 1)*x - z) + z*(2*y + 1)); out[6] = -0.5*(x - z + 1)*(y + z - 1)*(y + 1)*x; out[7] = -0.5*(x - z + 1)*(y + z - 1)*(x - 1)*y; out[8] = -0.5*(x - z + 1)*(((y + z + 1)*(x - 1)*y - z) + z*(2*x + 1)); // upper edges out[9] = z*(y + z - 1)*(x - z - 1); out[10] = -z*(x - z + 1)*(y + z - 1); out[11] = -z*((y + z + 1)*(x - z - 1) + 4*z); out[12] = z*(x - z + 1)*(y + z + 1); // base face out[13] = (x - z + 1)*(y + z - 1)*((y + 1)*(x - 1) - z*(x - y - z - 1)); } } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(14); // transform to reference element with base [-1,1]^2 const R x = 2.0*in[0] + in[2] - 1.0; const R y = 2.0*in[1] + in[2] - 1.0; const R z = in[2]; // transformation of the gradient leads to a multiplication // with the Jacobian [2 0 0; 0 2 0; 1 1 1] if (x > y) { // vertices out[0][0][0] = 0.5*(y - z - 1)*(y - z)*(2*x + 2*z - 1); out[0][0][1] = 0.5*(x + z)*(x + z - 1)*(2*y - 2*z - 1); out[0][0][2] = 0.5*(out[0][0][0] + out[0][0][1]) + 0.25*((2*x + 2*z - 1)*(y - z - 1)*(y - z) + (x + z)*(x + z - 1)*(-2*y + 2*z + 1)); out[1][0][0] = 2*(-0.25*((y - z)*((x + z + 1)*(-y + z + 1) - 4*z) + (x + z)*(y - z)*(-y + z + 1)) - z); out[1][0][1] = 2*(-0.25*((x + z)*((x + z + 1)*(-y + z + 1) - 4*z) + (x + z)*(y - z)*(-(x + z + 1))) + z); out[1][0][2] = 0.5*(out[1][0][0] + out[1][0][1]) - 0.25*((y - z)*((x + z + 1)*(-y + z + 1) - 4*z) - (x + z)*((x + z + 1)*(-y + z + 1) - 4*z) + (x + z)*(y - z)*(x - y + 2*z - 2)) - (x - y); out[2][0][0] = 0.5*(y - z)*(y - z + 1)*(2*x + 2*z - 1); out[2][0][1] = 0.5*(x + z)*(2*y - 2*z + 1)*(x + z - 1); out[2][0][2] = 0.5*(out[2][0][0] + out[2][0][1]) + 0.25*((y - x - 2*z)*(y - z + 1)*(x + z - 1) + (x + z)*(y - z)*(y - x - 2*z + 2)); out[3][0][0] = 0.5*(y - z)*(2*x + 2*z + 1)*(y - z + 1); out[3][0][1] = 0.5*(2*y - 2*z + 1)*(x + z)*(x + z + 1); out[3][0][2] = 0.5*(out[3][0][0] + out[3][0][1]) + 0.25*((y - x - 2*z)*(y - z + 1)*(x + z + 1) + (y - z)*(x + z)*(y - x - 2*z)); out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 4*z - 1; // lower edges out[5][0][0] = -((y - z + 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*((y - 1) + z)); out[5][0][1] = -((x + z - 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*((x + 1) - z)); out[5][0][2] = 0.5*(out[5][0][0] + out[5][0][1]) - 0.5*((-x + y - 2*z + 2)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*(x - y + 2*z + 1)); out[6][0][0] = -(y - z + 1)*(2*x + z + 1)*(y - 1); out[6][0][1] = -(((x + z + 1)*(y - 1)*x - z) + z*(2*y + 1) + (y - z + 1)*((x + z + 1)*x + 2*z)); out[6][0][2] = 0.5*(out[6][0][0] + out[6][0][1]) - 0.5*(-(((x + z + 1)*(y - 1)*x - z) + z*(2*y + 1)) + (y - z + 1)*(((y - 1)*x - 1) + 2*y + 1)); out[7][0][0] = -(((y - z - 1)*(x + 1)*y - z) + z*(2*x + 1) + (x + z - 1)*((y - z - 1)*y + 2*z)); out[7][0][1] = -(x + z - 1)*(2*y - z - 1)*(x + 1); out[7][0][2] = 0.5*(out[7][0][0] + out[7][0][1]) - 0.5*(((y - z - 1)*(x + 1)*y - z) + z*(2*x + 1) + (x + z - 1)*((-(x + 1)*y - 1) + 2*x + 1)); out[8][0][0] = -(y - z + 1)*(2*x + z)*y; out[8][0][1] = -(2*y - z + 1)*(x + z - 1)*(x + 1); out[8][0][2] = 0.5*(out[8][0][0] + out[8][0][1]) - 0.5*(-x + y - 2*z + 2)*(x + 1)*y; // upper edges out[9][0][0] = 2*z*(y - z - 1); out[9][0][1] = 2*z*(x + z - 1); out[9][0][2] = 0.5*(out[9][0][0] + out[9][0][1]) + (x + z - 1)*(y - z - 1) + z*(-x + y - 2*z); out[10][0][0] = -2*z*(y - z - 1); out[10][0][1] = -2*z*(x + z + 1); out[10][0][2] = 0.5*(out[10][0][0] + out[10][0][1]) - ((x + z + 1)*(y - z - 1) + 4*z) - z*(-x + y - 2*z + 2); out[11][0][0] = -2*z*(y - z + 1); out[11][0][1] = -2*z*(x + z - 1); out[11][0][2] = 0.5*(out[11][0][0] + out[11][0][1]) - (y - z + 1)*(x + z - 1) - z*(-x + y - 2*z + 2); out[12][0][0] = 2*z*(y - z + 1); out[12][0][1] = 2*z*(x + z + 1); out[12][0][2] = 0.5*(out[12][0][0] + out[12][0][1]) + (y - z + 1)*(x + z + 1) + z*(-x + y - 2*z); // base face out[13][0][0] = 2*((y - z + 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*(y - 1 + z)); out[13][0][1] = 2*((x + z - 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*(x + 1 - z)); out[13][0][2] = 0.5*(out[13][0][0] + out[13][0][1]) + ((-x + y - 2*z + 2)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*(x - y + 2*z + 1)); } else { // vertices out[0][0][0] = 0.5*(y + z)*(y + z - 1)*(2*x - 2*z - 1); out[0][0][1] = 0.5*(2*y + 2*z - 1)*(x - z - 1)*(x - z); out[0][0][2] = 0.5*(out[0][0][0] + out[0][0][1]) + 0.25*((2*y + 2*z - 1)*(x - z - 1)*(x - z) + (y + z)*(y + z - 1)*(-2*x + 2*z + 1)); out[1][0][0] = -0.5*(y + z)*(2*x - 2*z + 1)*(-y - z + 1); out[1][0][1] = -0.5*(x - z)*(x - z + 1)*(-2*y - 2*z + 1); out[1][0][2] = 0.5*(out[1][0][0] + out[1][0][1]) - 0.25*((x - y - 2*z)*(x - z + 1)*(-y - z + 1) + (x - z)*(y + z)*(-x + y + 2*z - 2)); out[2][0][0] = 0.5*((y + z)*((x - z - 1)*(y + z + 1) + 4*z) + (x - z)*(y + z)*(y + z + 1) + 4*z); out[2][0][1] = 0.5*((x - z)*((x - z - 1)*(y + z + 1) + 4*z) + (x - z)*(y + z)*(x - z - 1) - 4*z); out[2][0][2] = 0.5*(out[2][0][0] + out[2][0][1]) + 0.25*((x - y - 2*z)*((x - z - 1)*(y + z + 1) + 4*z) + (x - z)*(y + z)*(x - y - 2*z + 2) + 4*(x - y)); out[3][0][0] = 0.5*(y + z)*(2*x - 2*z + 1)*(y + z + 1); out[3][0][1] = 0.5*(x - z)*(x - z + 1)*(2*y + 2*z + 1); out[3][0][2] = 0.5*(out[3][0][0] + out[3][0][1]) + 0.25*((x - y - 2*z)*(x - z + 1)*(y + z + 1) + (y + z)*(x - z)*(x - y - 2*z)); out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 4*z - 1; // lower edges out[5][0][0] = -(y + z - 1)*(2*x - z - 1)*(y + 1); out[5][0][1] = -(((x - z - 1)*(y + 1)*x - z) + z*(2*y + 1) + (y + z - 1)*((x - z - 1)*x + 2*z)); out[5][0][2] = 0.5*(out[5][0][0] + out[5][0][1]) - 0.5*((((x - z - 1)*(y + 1)*x - z) + z*(2*y + 1)) + (y + z - 1)*((-(y + 1)*x - 1) + 2*y + 1)); out[6][0][0] = -(2*x - z + 1)*(y + z - 1)*(y + 1); out[6][0][1] = -(x - z + 1)*(2*y + z)*x; out[6][0][2] = 0.5*(out[6][0][0] + out[6][0][1]) - 0.5*(x - y - 2*z + 2)*(y + 1)*x; out[7][0][0] = -(2*x - z)*(y + z - 1)*y; out[7][0][1] = -(x - z + 1)*(2*y + z - 1)*(x - 1); out[7][0][2] = 0.5*(out[7][0][0] + out[7][0][1]) - 0.5*(x - y - 2*z + 2)*(x - 1)*y; out[8][0][0] = -(((y + z + 1)*(x - 1)*y - z) + z*(2*x + 1) + (x - z + 1)*((y + z + 1)*y + 2*z)); out[8][0][1] = -(x - z + 1)*(2*y + z + 1)*(x - 1); out[8][0][2] = 0.5*(out[8][0][0] + out[8][0][1]) - 0.5*(-(((y + z + 1)*(x - 1)*y - z) + z*(2*x + 1)) + (x - z + 1)*(((x - 1)*y - 1) + 2*x + 1)); // upper edges out[9][0][0] = 2*z*(y + z - 1); out[9][0][1] = 2*z*(x - z - 1); out[9][0][2] = 0.5*(out[9][0][0] + out[9][0][1]) + (y + z - 1)*(x - z - 1) + z*(x - y - 2*z); out[10][0][0] = -2*z*(y + z - 1); out[10][0][1] = -2*z*(x - z + 1); out[10][0][2] = 0.5*(out[10][0][0] + out[10][0][1]) - (x - z + 1)*(y + z - 1) - z*(x - y - 2*z + 2); out[11][0][0] = -2*z*(y + z + 1); out[11][0][1] = -2*z*(x - z - 1); out[11][0][2] = 0.5*(out[11][0][0] + out[11][0][1]) - ((y + z + 1)*(x - z - 1) + 4*z) - z*(x - y - 2*z + 2); out[12][0][0] = 2*z*(y + z + 1); out[12][0][1] = 2*z*(x - z + 1); out[12][0][2] = 0.5*(out[12][0][0] + out[12][0][1]) + (x - z + 1)*(y + z + 1) + z*(x - y - 2*z); // base face out[13][0][0] = 2*((y + z - 1)*((y + 1)*(x - 1) - z*(x - y - z - 1)) + (x - z + 1)*(y + z - 1)*(y + 1 - z)); out[13][0][1] = 2*((x - z + 1)*((y + 1)*(x - 1) - z*(x - y - z - 1)) + (x - z + 1)*(y + z - 1)*(x - 1 + z)); out[13][0][2] = 0.5*(out[13][0][0] + out[13][0][1]) + (x - y - 2*z + 2)*((y + 1)*(x - 1) - z*(x - y - z - 1)) + (x - z + 1)*(y + z - 1)*(-(x - y - 2*z - 1)); } } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); // transform to reference element with base [-1,1]^2 const R x = 2.0*in[0] + in[2] - 1.0; const R y = 2.0*in[1] + in[2] - 1.0; const R z = in[2]; auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); // transformation of the gradient leads to a multiplication // with the Jacobian [2 0 0; 0 2 0; 1 1 1] if (x > y) { switch (direction) { case 0: out[0] = 0.5*(y - z - 1)*(y - z)*(2*x + 2*z - 1); out[1] = 2*(-0.25*((y - z)*((x + z + 1)*(-y + z + 1) - 4*z) + (x + z)*(y - z)*(-y + z + 1)) - z); out[2] = 0.5*(y - z)*(y - z + 1)*(2*x + 2*z - 1); out[3] = 0.5*(y - z)*(2*x + 2*z + 1)*(y - z + 1); out[4] = 0; out[5] = -((y - z + 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*((y - 1) + z)); out[6] = -(y - z + 1)*(2*x + z + 1)*(y - 1); out[7] = -(((y - z - 1)*(x + 1)*y - z) + z*(2*x + 1) + (x + z - 1)*((y - z - 1)*y + 2*z)); out[8] = -(y - z + 1)*(2*x + z)*y; out[9] = 2*z*(y - z - 1); out[10] = -2*z*(y - z - 1); out[11] = -2*z*(y - z + 1); out[12] = 2*z*(y - z + 1); out[13] = 2*((y - z + 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*(y - 1 + z)); break; case 1: out[0] = 0.5*(x + z)*(x + z - 1)*(2*y - 2*z - 1); out[1] = 2*(-0.25*((x + z)*((x + z + 1)*(-y + z + 1) - 4*z) + (x + z)*(y - z)*(-(x + z + 1))) + z); out[2] = 0.5*(x + z)*(2*y - 2*z + 1)*(x + z - 1); out[3] = 0.5*(2*y - 2*z + 1)*(x + z)*(x + z + 1); out[4] = 0; out[5] = -((x + z - 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*((x + 1) - z)); out[6] = -(((x + z + 1)*(y - 1)*x - z) + z*(2*y + 1) + (y - z + 1)*((x + z + 1)*x + 2*z)); out[7] = -(x + z - 1)*(2*y - z - 1)*(x + 1); out[8] = -(2*y - z + 1)*(x + z - 1)*(x + 1); out[9] = 2*z*(x + z - 1); out[10] = -2*z*(x + z + 1); out[11] = -2*z*(x + z - 1); out[12] = 2*z*(x + z + 1); out[13] = 2*((x + z - 1)*((y - 1)*(x + 1) + z*(x - y + z + 1)) + (y - z + 1)*(x + z - 1)*(x + 1 - z)); break; case 2: out[0] = -((y - z)*(2*x + 2*z - 1)*(z - y + 1))/2; out[1] = ((y - z + 1)*(y - 2*x + z + 2*x*y - 2*x*z + 2*y*z - 2*z*z))/2; out[2] = ((y - z)*(2*x + 2*z - 1)*(y - z + 1))/2; out[3] = ((y - z)*(2*x + 2*z + 1)*(y - z + 1))/2; out[4] = 4*z - 1; out[5] = -((y - z + 1)*(2*y - 3*x + z + 2*x*y + 6*x*z - 2*y*z + 2*x*x + 4*z*z - 3))/2; out[6] = -((y - z + 1)*(3*y - 2*x + z + 3*x*y + x*z + y*z + x*x - 1))/2; out[7] = z - z*(2*x + 1) - ((2*z - y*(z - y + 1))*(x + z - 1))/2 - ((2*x - y*(x + 1))*(x + z - 1))/2 + ((x + 1)*(x + z - 1)*(z - 2*y + 1))/2 + y*(x + 1)*(z - y + 1); out[8] = -((y - z + 1)*(y + z + 3*x*y + x*z + y*z + x*x - 1))/2; out[9] = -(x + 3*z - 1)*(z - y + 1); out[10] = (x + z + 1)*(z - y + 1) - 2*y*z - 6*z + 2*z*z; out[11] = -(x + 3*z - 1)*(y - z + 1); out[12] = (x + 3*z + 1)*(y - z + 1); out[13] = (y - z + 1)*(2*y - 3*x + z + 2*x*y + 6*x*z - 2*y*z + 2*x*x + 4*z*z - 3); break; default: DUNE_THROW(RangeError, "Component out of range."); } } else // x <= y { switch (direction) { case 0: out[0] = -((y + z)*(2*z - 2*x + 1)*(y + z - 1))/2; out[1] = ((y + z)*(2*x - 2*z + 1)*(y + z - 1))/2; out[2] = -((y + z + 1)*(y - 3*z - 2*x*y - 2*x*z + 2*y*z + 2*z*z))/2; out[3] = ((y + z)*(2*x - 2*z + 1)*(y + z + 1))/2; out[4] = 0; out[5] = (y + 1)*(y + z - 1)*(z - 2*x + 1); out[6] = -(y + 1)*(2*x - z + 1)*(y + z - 1); out[7] = -y*(2*x - z)*(y + z - 1); out[8] = z - z*(2*x + 1) - (2*z + y*(y + z + 1))*(x - z + 1) - y*(x - 1)*(y + z + 1); out[9] = 2*z*(y + z - 1); out[10] = -2*z*(y + z - 1); out[11] = -2*z*(y + z + 1); out[12] = 2*z*(y + z + 1); out[13] = 2*(y + z - 1)*(2*x - z + 2*x*y - 2*x*z + 2*z*z); break; case 1: out[0] = -(x - z)*(y + z - 0.5)*(z - x + 1); out[1] = ((x - z)*(2*y + 2*z - 1)*(x - z + 1))/2; out[2] = -((z - x + 1)*(x + 3*z + 2*x*y + 2*x*z - 2*y*z - 2*z*z))/2; out[3] = ((x - z)*(2*y + 2*z + 1)*(x - z + 1))/2; out[4] = 0; out[5] = z - z*(2*y + 1) - (2*z - x*(z - x + 1))*(y + z - 1) + x*(y + 1)*(z - x + 1); out[6] = -x*(2*y + z)*(x - z + 1); out[7] = -(x - 1)*(x - z + 1)*(2*y + z - 1); out[8] = -(x - 1)*(x - z + 1)*(2*y + z + 1); out[9] = -2*z*(z - x + 1); out[10] = -2*z*(x - z + 1); out[11] = 2*z*(z - x + 1); out[12] = 2*z*(x - z + 1); out[13] = 2*(x - z + 1)*(2*x*y - z - 2*y + 2*y*z + 2*z*z); break; case 2: out[0] = -((x - z)*(2*y + 2*z - 1)*(z - x + 1))/2; out[1] = ((x - z)*(2*y + 2*z - 1)*(x - z + 1))/2; out[2] = ((x - z + 1)*(x - 2*y + z + 2*x*y + 2*x*z - 2*y*z - 2*z*z))/2; out[3] = ((x - z)*(2*y + 2*z + 1)*(x - z + 1))/2; out[4] = 4*z - 1; out[5] = z - z*(2*y + 1) - ((2*z - x*(z - x + 1))*(y + z - 1))/2 - ((2*y - x*(y + 1))*(y + z - 1))/2 + ((y + 1)*(y + z - 1)*(z - 2*x + 1))/2 + x*(y + 1)*(z - x + 1); out[6] = -((x - z + 1)*(x + z + 3*x*y + x*z + y*z + y*y - 1))/2; out[7] = -((x - z + 1)*(3*x*y - 4*y - z - x + x*z + y*z + y*y + 1))/2; out[8] = -((x - z + 1)*(3*x - 2*y + z + 3*x*y + x*z + y*z + y*y - 1))/2; out[9] = -(z - x + 1)*(y + 3*z - 1); out[10] = -(x - z + 1)*(y + 3*z - 1); out[11] = (y + z + 1)*(z - x + 1) - 2*x*z - 6*z + 2*z*z; out[12] = (x - z + 1)*(y + 3*z + 1); out[13] = (x - z + 1)*(2*x - 3*y + z + 2*x*y - 2*x*z + 6*y*z + 2*y*y + 4*z*z - 3); break; default: DUNE_THROW(RangeError, "Component out of range."); } } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 2; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp2/pyramidp2localcoefficients.hh000066400000000000000000000025571313314431100327700ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYRAMID_P2_LOCALCOEFFICIENTS_HH #define DUNE_PYRAMID_P2_LOCALCOEFFICIENTS_HH #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for PyramidP2 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class PyramidP2LocalCoefficients { public: //! \brief Standard constructor PyramidP2LocalCoefficients () : li(14) { // Vertex shape functions li[0] = LocalKey(0,3,0); li[1] = LocalKey(1,3,0); li[2] = LocalKey(2,3,0); li[3] = LocalKey(3,3,0); li[4] = LocalKey(4,3,0); // Edge shape functions li[5] = LocalKey(0,2,0); li[6] = LocalKey(1,2,0); li[7] = LocalKey(2,2,0); li[8] = LocalKey(3,2,0); li[9] = LocalKey(4,2,0); li[10] = LocalKey(5,2,0); li[11] = LocalKey(6,2,0); li[12] = LocalKey(7,2,0); // base face shape function li[13] = LocalKey(0,1,0); } //! number of coefficients std::size_t size () const { return 14; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/pyramidp2/pyramidp2localinterpolation.hh000066400000000000000000000033011313314431100332020ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYRAMID_P2_LOCALINTERPOLATION_HH #define DUNE_PYRAMID_P2_LOCALINTERPOLATION_HH #include namespace Dune { template class PyramidP2LocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; out.resize(14); typename LB::Traits::DomainType x; x[0] = 0.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[0] = y; x[0] = 1.0; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[1] = y; x[0] = 0.0; x[1] = 1.0; x[2] = 0.0; f.evaluate(x,y); out[2] = y; x[0] = 1.0; x[1] = 1.0; x[2] = 0.0; f.evaluate(x,y); out[3] = y; x[0] = 0.0; x[1] = 0.0; x[2] = 1.0; f.evaluate(x,y); out[4] = y; x[0] = 0.0; x[1] = 0.5; x[2] = 0.0; f.evaluate(x,y); out[5] = y; x[0] = 1.0; x[1] = 0.5; x[2] = 0.0; f.evaluate(x,y); out[6] = y; x[0] = 0.5; x[1] = 0.0; x[2] = 0.0; f.evaluate(x,y); out[7] = y; x[0] = 0.5; x[1] = 1.0; x[2] = 0.0; f.evaluate(x,y); out[8] = y; x[0] = 0.0; x[1] = 0.0; x[2] = 0.5; f.evaluate(x,y); out[9] = y; x[0] = 0.5; x[1] = 0.0; x[2] = 0.5; f.evaluate(x,y); out[10] = y; x[0] = 0.0; x[1] = 0.5; x[2] = 0.5; f.evaluate(x,y); out[11] = y; x[0] = 0.5; x[1] = 0.5; x[2] = 0.5; f.evaluate(x,y); out[12] = y; x[0] = 0.5; x[1] = 0.5; x[2] = 0.0; f.evaluate(x,y); out[13] = y; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/q1.hh000066400000000000000000000060041313314431100240650ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_Q1_LOCALFINITEELEMENT_HH #define DUNE_Q1_LOCALFINITEELEMENT_HH #include #include #include #include #include #include namespace Dune { /** \brief The local Q1 finite element on cubes \tparam D Domain data type \tparam R Range data type \tparam dim Dimension of the simplex */ template class Q1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits,Q1LocalCoefficients, Q1LocalInterpolation > > Traits; /** \todo Please doc me ! */ Q1LocalFiniteElement () { gt.makeCube(dim); } Q1LocalFiniteElement (const Q1LocalFiniteElement & o) : gt(o.gt) {} /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } Q1LocalFiniteElement* clone () const { return new Q1LocalFiniteElement(*this); } private: Q1LocalBasis basis; Q1LocalCoefficients coefficients; Q1LocalInterpolation > interpolation; GeometryType gt; }; //! Factory for global-valued Q1 elements /** * \tparam Geometry Type of the geometry. Used to extract the domain field * type and the dimension. * \tparam RF Range field type. */ template class Q1FiniteElementFactory : public ScalarLocalToGlobalFiniteElementAdaptorFactory< Q1LocalFiniteElement< typename Geometry::ctype, RF, Geometry::mydimension >, Geometry > { typedef Q1LocalFiniteElement< typename Geometry::ctype, RF, Geometry::mydimension > LFE; typedef ScalarLocalToGlobalFiniteElementAdaptorFactory Base; static const LFE lfe; public: //! default constructor Q1FiniteElementFactory() : Base(lfe) {} }; template const typename Q1FiniteElementFactory::LFE Q1FiniteElementFactory::lfe; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/q1/000077500000000000000000000000001313314431100235445ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/q1/CMakeLists.txt000066400000000000000000000002361313314431100263050ustar00rootroot00000000000000install(FILES q1localbasis.hh q1localcoefficients.hh q1localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/q1) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/q1/q1localbasis.hh000066400000000000000000000075141313314431100264520ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_Q1_LOCALBASIS_HH #define DUNE_Q1_LOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lagrange shape functions of order 1 on the reference cube. Also known as \f$Q^1\f$. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam dim Dimension of the cube \nosubgrouping */ template class Q1LocalBasis { public: typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 1<& out) const { out.resize(size()); for (size_t i=0; i& out) const // return value { out.resize(size()); // Loop over all shape functions for (size_t i=0; i& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); if (direction >= dim) { DUNE_THROW(RangeError, "Direction of partial derivative not found!"); } // Loop over all shape functions for (std::size_t i = 0; i < size(); ++i) { // Initialize: the overall expression is a product // if j-th bit of i is set to -1, else 1 out[i] = (i & (1< #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for Q1 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class Q1LocalCoefficients { public: //! \brief Standard constructor Q1LocalCoefficients () : li(1< li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/q1/q1localinterpolation.hh000066400000000000000000000017341313314431100302360ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_Q1_LOCALINTERPOLATION_HH #define DUNE_Q1_LOCALINTERPOLATION_HH #include namespace Dune { /** \todo Please doc me! */ template class Q1LocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; out.resize(1< #include #include #include #include "pk.hh" #include "qk.hh" namespace Dune { //! Factory for global-valued Q23D elements /** * \tparam Geometry Type of the geometry. Used to extract the domain field * type. * \tparam RF Range field type. */ template class Q2FiniteElementFactory : public ScalarLocalToGlobalFiniteElementAdaptorFactory< typename std::conditional, QkLocalFiniteElement >::type, Geometry> { typedef typename std::conditional, QkLocalFiniteElement >::type LFE; typedef ScalarLocalToGlobalFiniteElementAdaptorFactory Base; static const LFE lfe; public: //! default constructor Q2FiniteElementFactory() : Base(lfe) {} }; template const typename Q2FiniteElementFactory::LFE Q2FiniteElementFactory::lfe; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/qk.hh000066400000000000000000000041351313314431100241620ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_QK_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_QK_LOCALFINITEELEMENT_HH #include "qk/qklocalinterpolation.hh" #include "qk/qklocalbasis.hh" #include "qk/qklocalcoefficients.hh" namespace Dune { /** \brief General Lagrange finite element for cubes with arbitrary dimension and polynomial order * \note The general class QkLocalCoefficients is available for k>0 in dimensions 2 and 3 only * * \tparam D type used for domain coordinates * \tparam R type used for function values * \tparam d dimension of the reference element * \tparam k polynomial order */ template class QkLocalFiniteElement { typedef QkLocalBasis LocalBasis; typedef QkLocalCoefficients LocalCoefficients; typedef QkLocalInterpolation LocalInterpolation; public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits,LocalInterpolation> Traits; /** \todo Please doc me ! */ QkLocalFiniteElement () { gt.makeCube(d); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } QkLocalFiniteElement* clone () const { return new QkLocalFiniteElement(*this); } private: LocalBasis basis; LocalCoefficients coefficients; LocalInterpolation interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/qk/000077500000000000000000000000001313314431100236365ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/lagrange/qk/CMakeLists.txt000066400000000000000000000002361313314431100263770ustar00rootroot00000000000000install(FILES qklocalbasis.hh qklocalcoefficients.hh qklocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/qk) dune-localfunctions-2.5.1/dune/localfunctions/lagrange/qk/qklocalbasis.hh000066400000000000000000000141551313314431100266350ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_QKLOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_QKLOCALBASIS_HH #include #include #include #include #include #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lagrange shape functions of order k on the reference cube. Also known as \f$Q^k\f$. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam k Polynomial degree \tparam d Dimension of the cube \nosubgrouping */ template class QkLocalBasis { enum { n = StaticPower::power }; // ith Lagrange polynomial of degree k in one dimension static R p (int i, D x) { R result(1.0); for (int j=0; j<=k; j++) if (j!=i) result *= (k*x-j)/(i-j); return result; } // derivative of ith Lagrange polynomial of degree k in one dimension static R dp (int i, D x) { R result(0.0); for (int j=0; j<=k; j++) if (j!=i) { R prod( (k*1.0)/(i-j) ); for (int l=0; l<=k; l++) if (l!=i && l!=j) prod *= (k*x-l)/(i-l); result += prod; } return result; } // Return i as a d-digit number in the (k+1)-nary system static Dune::FieldVector multiindex (int i) { Dune::FieldVector alpha; for (int j=0; j,R,1,Dune::FieldVector,Dune::FieldMatrix, 1> Traits; //! \brief number of shape functions unsigned int size () const { return StaticPower::power; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); for (size_t i=0; i alpha(multiindex(i)); // initialize product out[i] = 1.0; // dimension by dimension for (int j=0; j& out) const { out.resize(size()); // Loop over all shape functions for (size_t i=0; i alpha(multiindex(i)); // Loop over all coordinate directions for (int j=0; j& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); switch (totalOrder) { case 0: evaluateFunction(in,out); break; case 1: { out.resize(size()); // Loop over all shape functions for (size_t i=0; i alpha(multiindex(i)); // Initialize: the overall expression is a product out[i][0] = 1.0; // rest of the product for (std::size_t l=0; l inline void DUNE_DEPRECATED_MSG("Use method 'partial' instead!") evaluate( const std::array& direction, const typename Traits::DomainType& in, std::vector& out) const { static_assert(diffOrder == 1, "We only can compute first derivatives"); out.resize(size()); // Loop over all shape functions for (size_t i=0; i alpha(multiindex(i)); // Loop over all coordinate directions std::size_t j = direction[0]; // Initialize: the overall expression is a product // if j-th bit of i is set to -1, else 1 out[i][0] = dp(alpha[j],in[j]); // rest of the product for (std::size_t l=0; l #include #include #include #include #include namespace Dune { /** \brief Attaches a shape function to an entity * * \tparam k Polynomial order * \tparam d Dimension of the reference cube */ template class QkLocalCoefficients { static const unsigned unsignedK = k; // Return i as a d-digit number in the (k+1)-nary system static std::array multiindex (unsigned int i) { std::array alpha; for (int j=0; j& subEntity) { // Special-handling for piecewise constant elements if (k==0) { subEntity[0] = 0; return; } unsigned lastIndex=0; /* edge and vertex numbering 0----0----1 */ // edge (0) subEntity[lastIndex++] = 0; // corner 0 for (unsigned i = 0; i < unsignedK - 1; ++i) subEntity[lastIndex++] = 0; // inner dofs of element (0) subEntity[lastIndex++] = 1; // corner 1 assert((StaticPower::power==lastIndex)); } void setup2d(std::vector& subEntity) { // Special-handling for piecewise constant elements if (k==0) { subEntity[0] = 0; return; } unsigned lastIndex=0; // LocalKey: entity number, entity codim, dof indices within each entity /* edge and vertex numbering 2----3----3 | | | | 0 1 | | | | 0----2----1 */ // lower edge (2) subEntity[lastIndex++] = 0; // corner 0 for (unsigned i = 0; i < unsignedK - 1; ++i) subEntity[lastIndex++] = 2; // inner dofs of lower edge (2) subEntity[lastIndex++] = 1; // corner 1 // iterate from bottom to top over inner edge dofs for (unsigned e = 0; e < unsignedK - 1; ++e) { subEntity[lastIndex++] = 0; // left edge (0) for (unsigned i = 0; i < unsignedK - 1; ++i) subEntity[lastIndex++] = 0; // face dofs subEntity[lastIndex++] = 1; // right edge (1) } // upper edge (3) subEntity[lastIndex++] = 2; // corner 2 for (unsigned i = 0; i < unsignedK - 1; ++i) subEntity[lastIndex++] = 3; // inner dofs of upper edge (3) subEntity[lastIndex++] = 3; // corner 3 assert((StaticPower::power==lastIndex)); } void setup3d(std::vector& subEntity) { // Special-handling for piecewise constant elements if (k==0) { subEntity[0] = 0; return; } unsigned lastIndex=0; #ifndef NDEBUG const unsigned numIndices = StaticPower::power; const unsigned numFaceIndices = StaticPower::power; #endif const unsigned numInnerEdgeDofs = k-1; // LocalKey: entity number, entity codim, dof indices within each entity /* edge and vertex numbering 6---(11)--7 6---------7 /| /| /| (5) /| (8)| (9)| / | top / | / (2) / (3) / |(3)bac/k | 4---(10)--5 | 4---------5 | | | | | left|(0)| |(1)|right | 2--(7)|---3 | 2-----|---3 (0) / (1) / |(2)front | / |(4) |(5) | / (4) | / |/ |/ |/ bottom |/ 0---(6)---1 0---------1 */ // bottom face (4) lastIndex=0; // lower edge (6) subEntity[lastIndex++] = 0; // corner 0 for (unsigned i = 0; i < numInnerEdgeDofs; ++i) subEntity[lastIndex++] = 6; // inner dofs of lower edge (6) subEntity[lastIndex++] = 1; // corner 1 // iterate from bottom to top over inner edge dofs for (unsigned e = 0; e < numInnerEdgeDofs; ++e) { subEntity[lastIndex++] = 4; // left edge (4) for (unsigned i = 0; i < numInnerEdgeDofs; ++i) subEntity[lastIndex++] = 4; // inner face dofs subEntity[lastIndex++] = 5; // right edge (5) } // upper edge (7) subEntity[lastIndex++] = 2; // corner 2 for (unsigned i = 0; i < unsignedK - 1; ++i) subEntity[lastIndex++] = 7; // inner dofs of upper edge (7) subEntity[lastIndex++] = 3; // corner 3 assert(numFaceIndices==lastIndex); // added 1 face so far /////////////////////////////////////////// end bottom face (4) ///////////////////// inner faces for(unsigned f = 0; f < numInnerEdgeDofs; ++f) { // lower edge (connecting edges 0 and 1) subEntity[lastIndex++] = 0; // dof on edge 0 for (unsigned i = 0; i < numInnerEdgeDofs; ++i) subEntity[lastIndex++] = 2; // dof in front face subEntity[lastIndex++] = 1; // dof on edge 1 // iterate from bottom to top over inner edge dofs for (unsigned e = 0; e < numInnerEdgeDofs; ++e) { subEntity[lastIndex++] = 0; // on left face (0) for (unsigned i = 0; i < numInnerEdgeDofs; ++i) subEntity[lastIndex++] = 0; // volume dofs subEntity[lastIndex++] = 1; // right face (1) } // upper edge (connecting edges 0 and 1) subEntity[lastIndex++] = 2; // dof on edge 2 for (unsigned i = 0; i < numInnerEdgeDofs; ++i) subEntity[lastIndex++] = 3; // dof on rear face (3) subEntity[lastIndex++] = 3; // dof on edge 3 assert(lastIndex==(f+1+1)*numFaceIndices); } ////////////////////////////////////////// top face (5) // lower edge (10) subEntity[lastIndex++] = 4; // corner 4 for (unsigned i = 0; i < unsignedK - 1; ++i) subEntity[lastIndex++] = 10; // inner dofs on lower edge (10) subEntity[lastIndex++] = 5; // corner 5 // iterate from bottom to top over inner edge dofs for (unsigned e = 0; e < unsignedK - 1; ++e) { subEntity[lastIndex++] = 8; // left edge (8) for (unsigned i = 0; i < unsignedK - 1; ++i) subEntity[lastIndex++] = 5; // face dofs subEntity[lastIndex++] = 9; // right edge (9) } // upper edge (11) subEntity[lastIndex++] = 6; // corner 6 for (unsigned i = 0; i < unsignedK - 1; ++i) subEntity[lastIndex++] = 11; // inner dofs of upper edge (11) subEntity[lastIndex++] = 7; // corner 7 assert(numIndices==lastIndex); } public: //! \brief Default constructor QkLocalCoefficients () : li(StaticPower::power) { // Set up array of codimension-per-dof-number std::vector codim(li.size()); for (std::size_t i=0; i mIdx = multiindex(i); for (int j=0; j index(size()); for (std::size_t i=0; i mIdx = multiindex(i); for (int j=d-1; j>=0; j--) if (mIdx[j]>0 and mIdx[j] subEntity(li.size()); if (k==1) { // We can handle the first-order case in any dimension for (std::size_t i=0; i::power; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/lagrange/qk/qklocalinterpolation.hh000066400000000000000000000035411313314431100304200ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_QKLOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_QKLOCALINTERPOLATION_HH #include #include #include #include #include namespace Dune { /** \todo Please doc me! */ template class QkLocalInterpolation { // Return i as a d-digit number in the (k+1)-nary system static Dune::FieldVector multiindex (int i) { Dune::FieldVector alpha; for (int j=0; j void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; out.resize(StaticPower::power); for (int i=0; i::power; i++) { // convert index i to multiindex Dune::FieldVector alpha(multiindex(i)); // Generate coordinate of the i-th Lagrange point for (int j=0; j class QkLocalInterpolation<0,d,LB> { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::DomainType x(0); typename LB::Traits::RangeType y; f.evaluate(x,y); out.resize(1); out[0] = y; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/meta/000077500000000000000000000000001313314431100223715ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/meta/CMakeLists.txt000066400000000000000000000001661313314431100251340ustar00rootroot00000000000000add_subdirectory(power) install(FILES power.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/meta) dune-localfunctions-2.5.1/dune/localfunctions/meta/power.hh000066400000000000000000000104721313314431100240520ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_META_POWER_HH #define DUNE_LOCALFUNCTIONS_META_POWER_HH #include #include #include #include #include #include namespace Dune { //! \brief Meta-finite element turning a scalar finite element into //! vector-valued one /** * @ingroup FiniteElementImplementation * * \tparam Backend Type of finite element to take the power of. * \tparam dimR Power to raise the finite element to. */ template class PowerFiniteElement { public: //! types of component objects struct Traits { //! type of the Basis typedef PowerBasis Basis; //! type of the Coefficients typedef PowerCoefficients Coefficients; //! type of the Interpolation typedef PowerInterpolation Interpolation; }; private: std::shared_ptr backend; typename Traits::Basis basis_; typename Traits::Coefficients coefficients_; typename Traits::Interpolation interpolation_; public: //! Construct a finite element /** * \note With this constructor a copy of the backend finite element is * stored in this object. */ PowerFiniteElement(const Backend &backend_) : backend(new Backend(backend_)), basis_(backend->basis()), coefficients_(backend->coefficients(), dimR), interpolation_(backend->interpolation()) { } //! Construct a finite element /** * \note With this constructor ownership of the backend finite element is * determined by the shared_ptr. */ PowerFiniteElement(const std::shared_ptr &backendSPtr) : backend(backendSPtr), basis_(backend->basis()), coefficients_(backend->coefficients(), dimR), interpolation_(backend->interpolation()) { } //! Extract basis of this finite element /** * The returned lvalue must have a lifetime at least as long as the finite * element object it was acquired from. */ const typename Traits::Basis& basis() const { return basis_; } //! Extract coefficients of this finite element /** * The returned lvalue must have a lifetime at least as long as the finite * element object it was acquired from. */ const typename Traits::Coefficients& coefficients() const { return coefficients_; } //! Extract interpolation of this finite element /** * The returned lvalue must have a lifetime at least as long as the finite * element object it was acquired from. */ const typename Traits::Interpolation& interpolation() const { return interpolation_; } //! Extract geometry type of this finite element GeometryType type() const { return backend->type(); } }; //! \brief Factory for meta-finite elements turning scalar finite elements //! into vector-valued ones /** * \implements FiniteElementFactory * \ingroup FiniteElementFactoryImplementation * * \tparam BackendFiniteElement Type of finite element to take the power of. * \tparam dimR Power to raise the finite element to. */ template class PowerFiniteElementFactory { public: //! Type of the finite element typedef PowerFiniteElement FiniteElement; //! create a finite element /** * \note With this overload of make() the backend finite element is copied * into the created object. */ const FiniteElement make(const BackendFiniteElement &backend) const { return FiniteElement(backend); } //! create a finite element /** * \note With this overload of make() ownership of the backend finite * element is determined by the shared_ptr. */ const FiniteElement make(const std::shared_ptr &backendSPtr) const { return FiniteElement(backendSPtr); } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_META_POWER_HH dune-localfunctions-2.5.1/dune/localfunctions/meta/power/000077500000000000000000000000001313314431100235255ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/meta/power/CMakeLists.txt000066400000000000000000000002101313314431100262560ustar00rootroot00000000000000install(FILES basis.hh coefficients.hh interpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/meta/power) dune-localfunctions-2.5.1/dune/localfunctions/meta/power/basis.hh000066400000000000000000000075241313314431100251570ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_META_POWER_BASIS_HH #define DUNE_LOCALFUNCTIONS_META_POWER_BASIS_HH #include #include #include #include #include namespace Dune { //! Meta-basis turning a scalar basis into vector-valued basis /** * @ingroup BasisImplementation * * \tparam Backend Type of basis to take the power of. * \tparam dimR Power to raise the basis to. */ template class PowerBasis { static_assert(Backend::Traits::dimRange == 1, "PowerBasis works only with scalar backends"); // don't use a reference here so this class stays copyable const Backend *backend; public: //! types of domain and range struct Traits : public Backend::Traits { //! Dimension of the range values static const std::size_t dimRange = dimR; //! Type used for range values typedef FieldVector Range; //! Jacobian properties /** * \note The Jacobian should be some matrix type with \c dimRange x * \c dimDomainGlobal components of type \c RangeField. */ typedef FieldMatrix Jacobian; //! maximum number of partial derivatives supported static const std::size_t diffOrder = Backend::Traits::diffOrder > 0 ? 1 : 0; }; //! Construct a PowerBasis /** * \param backend_ Backend basis object to construct this object from. * This object holds a reference to the backend object. * This reference is also copied when this object is * copied. */ PowerBasis(const Backend &backend_) : backend(&backend_) { } //! Number of shape functions std::size_t size () const { return backend->size()*dimR; } //! Polynomial order of the shape functions for quadrature std::size_t order () const { return backend->order(); } //! Evaluate all shape functions at given position void evaluateFunction(const typename Traits::DomainLocal& in, std::vector& out) const { std::vector backendValues; backend->evaluateFunction(in, backendValues); out.assign(size(), typename Traits::Range(0)); for(std::size_t d = 0; d < dimR; ++d) for(std::size_t i = 0; i < backend->size(); ++i) out[d*backend->size()+i][d] = backendValues[i][0]; } //! Evaluate Jacobian of all shape functions at given position void evaluateJacobian(const typename Traits::DomainLocal& in, std::vector& out) const { std::vector backendValues; backend->evaluateJacobian(in, backendValues); out.assign(size(), typename Traits::Jacobian(0)); for(std::size_t d = 0; d < dimR; ++d) for(std::size_t i = 0; i < backend->size(); ++i) out[d*backend->size()+i][d] = backendValues[i][0]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainLocal& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_META_POWER_BASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/meta/power/coefficients.hh000066400000000000000000000031561313314431100265140ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_META_POWER_COEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_META_POWER_COEFFICIENTS_HH #include #include #include namespace Dune { //! \brief Meta-coefficients turning a scalar coefficients into //! vector-valued coefficients /** * \nosubgrouping * \implements CoefficientsInterface */ class PowerCoefficients { std::vector keys; public: //! Construct a PowerCoefficients object /** * \param backend The backend coeficients object to raise to a power. * \param power Power to raise the backend object to. * * The LocalKeys of the backend coefficients are copied into internal * storage. The index member of each LocalKey is modified to keep them * unique for instances of different power. */ template PowerCoefficients(const Backend &backend, std::size_t power) : keys(backend.size()*power) { for(std::size_t i = 0; i < backend.size(); ++i) { const LocalKey &k = backend.localKey(i); for(std::size_t d = 0; d < power; ++d) keys[i+d*backend.size()] = LocalKey(k.subEntity(), k.codim(), power*k.index() + d); } } //! number of coefficients inline std::size_t size() const { return keys.size(); } //! get i'th index inline const LocalKey& localKey(std::size_t i) const { return keys[i]; } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_META_POWER_COEFFICIENTS_HH dune-localfunctions-2.5.1/dune/localfunctions/meta/power/interpolation.hh000066400000000000000000000056341313314431100267450ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_META_POWER_INTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_META_POWER_INTERPOLATION_HH #include #include #include #include namespace Dune { //! \brief Meta-interpolation turning a scalar interpolation into //! vector-valued interpolation /** * \tparam Backend Type of the scalar interpolation. * \tparam BasisTraits Traits type of the corresponding PowerBasis. * * \nosubgrouping */ template class PowerInterpolation { static_assert(Backend::Traits::dimRange == 1, "PowerInterpolation works only with scalar backends"); const Backend *backend; public: //! Export basis traits typedef BasisTraits Traits; //! Construct a PowerInterpolation /** * \param backend_ Backend interpolation object to construct this object * from. This object holds a reference to the backend * object. This reference is also copied when this object * is copied. */ PowerInterpolation(const Backend &backend_) : backend(&backend_) { } private: template class ComponentEvaluator { const F &f; std::size_t comp; public: ComponentEvaluator(const F &f_, std::size_t comp_) : f(f_), comp(comp_) { } void evaluate(const typename Backend::Traits::DomainLocal &x, typename Backend::Traits::Range &y) const { typename Traits::Range fy; f.evaluate(x, fy); y[0] = fy[comp]; } }; public: //! Determine coefficients interpolating a given function /** * \param f An object supporting the expression \c f.evaluate(x,y), * where \c x is of type \c Traits::DomainLocal and \c y of the * type \c Traits::Range. When \c f.evaluate(x,y) is * evaluated, \c x will be a local coordinate, and the * expression should set \c y to the function value at that * position. The initial value of \c y should not be used. * \param out Vector where to store the interpolated coefficients. */ template void interpolate(const F& f, std::vector& out) const { out.clear(); std::vector cout; for(std::size_t d = 0; d < Traits::dimRange; ++d) { backend->interpolate(ComponentEvaluator(f, d), cout); if(d == 0) out.resize(cout.size()*Traits::dimRange); // make sure the size of cout does not change surprisingly assert(out.size() == cout.size()*Traits::dimRange); std::copy(cout.begin(), cout.end(), out.begin() + d*cout.size()); } } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_META_POWER_INTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/mimetic.hh000066400000000000000000000031771313314431100234230ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_MIMETICLOCALFINITEELEMENT_HH #define DUNE_MIMETICLOCALFINITEELEMENT_HH #include #include "common/localfiniteelementtraits.hh" #include "mimetic/mimeticall.hh" namespace Dune { /** * \ingroup Mimetic * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * \tparam dim Domain dimension */ template class MimeticLocalFiniteElement { Dune::GeometryType gt; MimeticLocalBasis basis; MimeticLocalCoefficients coefficients; MimeticLocalInterpolation > interpolation; public: typedef Dune::LocalFiniteElementTraits, MimeticLocalCoefficients, MimeticLocalInterpolation > > Traits; MimeticLocalFiniteElement () {} MimeticLocalFiniteElement (Dune::GeometryType::BasicType basicType) : gt(basicType,dim) {} MimeticLocalFiniteElement (Dune::GeometryType::BasicType basicType, unsigned int variant) : gt(basicType,dim), basis(variant), coefficients(variant) {} const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } Dune::GeometryType type () const { return gt; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/mimetic/000077500000000000000000000000001313314431100230725ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/mimetic/CMakeLists.txt000066400000000000000000000001451313314431100256320ustar00rootroot00000000000000install(FILES mimeticall.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/mimetic) dune-localfunctions-2.5.1/dune/localfunctions/mimetic/mimeticall.hh000066400000000000000000000057041313314431100255410ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_MIMETIC_ALL_HH #define DUNE_MIMETIC_ALL_HH #include #include #include #include #include #include "../common/localbasis.hh" #include "../common/localkey.hh" namespace Dune { template class MimeticLocalBasis { public: typedef Dune::LocalBasisTraits, R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; MimeticLocalBasis (unsigned int variant_) : variant(variant_) {} MimeticLocalBasis () : variant(0) {} unsigned int size () const { return variant; } //! \brief Evaluate all shape functions inline void evaluateFunction ( const typename Traits::DomainType& in, std::vector& out) const { DUNE_THROW(Dune::Exception,"mimetic basis evaluation not available"); } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian ( const typename Traits::DomainType& in, std::vector& out) const { DUNE_THROW(Dune::Exception,"mimetic basis Jacobian evaluation not available"); } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& /*order*/, const typename Traits::DomainType& /*in*/, // position std::vector& /*out*/) const // return value { DUNE_THROW(Dune::Exception,"mimetic basis partial derivative evaluation not available"); } //! \brief Polynomial order of the shape functions unsigned int order () const { DUNE_THROW(Dune::Exception,"mimetic order evaluation not available"); } private: unsigned int variant; }; template class MimeticLocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& f, std::vector& out) const { DUNE_THROW(Dune::Exception,"mimetic local interpolation not available"); } }; /** \brief ! \implements Dune::LocalCoefficientsVirtualImp */ class MimeticLocalCoefficients { public: MimeticLocalCoefficients (unsigned int variant_) : variant(variant_), li(variant_) { for (unsigned int i=0; i li; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/monomial.hh000066400000000000000000000140321313314431100235770ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_MONOMIAL_HH #define DUNE_LOCALFUNCTIONS_MONOMIAL_HH #include #include #include #include #include #include #include "common/localfiniteelementtraits.hh" #include "common/localtoglobaladaptors.hh" #include "monomial/monomiallocalbasis.hh" #include "monomial/monomiallocalcoefficients.hh" #include "monomial/monomiallocalinterpolation.hh" namespace Dune { /** \brief Monomial basis for discontinuous Galerkin methods * * Be careful: Although MonomialLocalInterpolation::interpolate * uses an L^2 projection it is unstable for higher polynomial degrees. * * \ingroup Monomial * * \tparam D Type used for coordinates * \tparam R Type used for shape function values * \tparam d Dimension of the element * \tparam p Order of the basis * \tparam diffOrder Maximum differentiation order to report in the traits. */ template class MonomialLocalFiniteElement { enum { static_size = MonomImp::Size::val }; public: /** Traits class */ typedef LocalFiniteElementTraits< MonomialLocalBasis, MonomialLocalCoefficients, MonomialLocalInterpolation,static_size> > Traits; //! Construct a MonomLocalFiniteElement MonomialLocalFiniteElement (const GeometryType >_) : basis(), interpolation(gt_, basis), gt(gt_) {} /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } private: MonomialLocalBasis basis; MonomialLocalCoefficients coefficients; MonomialLocalInterpolation,static_size> interpolation; GeometryType gt; }; //! Factory for global-valued MonomFiniteElement objects /** * Constructs MonomialFiniteElement objects given a geometry. * * \tparam Geometry Geometry for the local to global transformation. * \tparam RF Field type of the range. * \tparam p Order of the basis. * * \implements FiniteElementFactoryInterface * * \note There is no real MonomFiniteElement, only the FiniteElement typedef * inside this class. */ template class MonomialFiniteElementFactory { typedef typename Geometry::ctype DF; static const std::size_t dim = Geometry::mydimension; typedef MonomialLocalFiniteElement LocalFE; std::vector > localFEs; void init(const GeometryType >) { std::size_t index = gt.id() >> 1; if(localFEs.size() <= index) localFEs.resize(index+1); localFEs[index].reset(new LocalFE(gt)); } public: typedef ScalarLocalToGlobalFiniteElementAdaptor FiniteElement; //! construct a MonomialFiniteElementFactory from a list of GeometryType's /** * \param begin Begin of a range of geometry types. * \param end End of a range of geometry types. */ template MonomialFiniteElementFactory(const ForwardIterator &begin, const ForwardIterator &end) { for(ForwardIterator it = begin; it != end; ++it) init(*it); } //! construct a MonomialFiniteElementFactory from a single GeometryType /** * \param gt GeometryType to construct elements with */ MonomialFiniteElementFactory(const GeometryType >) { init(gt); } //! construct a MonomFiniteElementFactory for all applicable GeometryType's /** * \note This constructor only works for dimensions up to and including 3. */ MonomialFiniteElementFactory() { static_assert(dim <= 3, "MonomFiniteElementFactory knows the " "available geometry types only up to dimension 3"); GeometryType gt; switch(dim) { case 0 : gt.makeVertex(); init(gt); break; case 1 : gt.makeLine(); init(gt); break; case 2 : gt.makeTriangle(); init(gt); gt.makeQuadrilateral(); init(gt); break; case 3 : gt.makeTetrahedron(); init(gt); gt.makePyramid(); init(gt); gt.makePrism(); init(gt); gt.makeHexahedron(); init(gt); break; default : // this should never happen -- it should be caught by the static // assert above. std::abort(); }; } //! construct a global-valued MonomFiniteElement /** * \param geometry The geometry object to use for adaption. * * \note The returned object stores the reference to the geometry passed * here as well as references to internal data of this factory. Any * use of the returned value after the geometry reference or the * factory object was become invalid results in undefined behaviour. * The exception is that the destructor of the returned value may * still be called. */ const FiniteElement make(const Geometry& geometry) { std::size_t index = geometry.type().id() >> 1; assert(localFEs.size() > index && localFEs[index]); return FiniteElement(*localFEs[index], geometry); } }; } #endif // DUNE_LOCALFUNCTIONS_MONOMIAL_HH dune-localfunctions-2.5.1/dune/localfunctions/monomial/000077500000000000000000000000001313314431100232565ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/monomial/CMakeLists.txt000066400000000000000000000002551313314431100260200ustar00rootroot00000000000000install(FILES monomiallocalbasis.hh monomiallocalcoefficients.hh monomiallocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/monomial) dune-localfunctions-2.5.1/dune/localfunctions/monomial/monomiallocalbasis.hh000066400000000000000000000256771313314431100274700ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALBASIS_HH #include #include #include #include #include #include "../common/localbasis.hh" namespace Dune { namespace MonomImp { /** template meta program to calculate the number of shape functions * \internal */ template struct Size { enum { val = Size::val+Size::val }; }; template struct Size { enum { val = 1 }; }; template struct Size<0, k> { enum { val = 1 }; }; template<> struct Size<0, 0> { enum { val = 1 }; }; template T ipow(T base, int exp) { T result(1); while (exp) { if (exp & 1) result *= base; exp >>= 1; base *= base; } return result; } //! Access output vector of evaluateFunction() and evaluate() template class EvalAccess { std::vector &out; #ifndef NDEBUG unsigned int first_unused_index; #endif public: EvalAccess(std::vector &out_) : out(out_) #ifndef NDEBUG , first_unused_index(0) #endif { } #ifndef NDEBUG ~EvalAccess() { assert(first_unused_index == out.size()); } #endif typename Traits::RangeFieldType &operator[](unsigned int index) { assert(index < out.size()); #ifndef NDEBUG if(first_unused_index <= index) first_unused_index = index+1; #endif return out[index][0]; } }; //! Access output vector of evaluateJacobian() template class JacobianAccess { std::vector &out; unsigned int row; #ifndef NDEBUG unsigned int first_unused_index; #endif public: JacobianAccess(std::vector &out_, unsigned int row_) : out(out_), row(row_) #ifndef NDEBUG , first_unused_index(0) #endif { } #ifndef NDEBUG ~JacobianAccess() { assert(first_unused_index == out.size()); } #endif typename Traits::RangeFieldType &operator[](unsigned int index) { assert(index < out.size()); #ifndef NDEBUG if(first_unused_index <= index) first_unused_index = index+1; #endif return out[index][0][row]; } }; /** Template Metaprogramm for evaluating monomial shapefunctions * \internal * * \tparam Traits The Traits class of the monomial shape functions to * evaluate -- used to get DomainType etc. * \tparam c The "codim of the next dimension to try for factors". * Unfortunately, we cannot recurs over that dimension * directly, since the end of the recursion cannot be * specialized for dimDomain-1, but we can recurs over * dimDomain minus that dimension, since it can be * specialized for 1. */ template struct Evaluate { enum { //! The next dimension to try for factors d = Traits::dimDomain - c }; /** \todo * * \tparam Access Wrapper around the result vector, so we don't have to * copy the output and can still use the same code for * both the usual drivatives and for the Jacobian */ template static void eval ( //! The point at which to evaluate const typename Traits::DomainType &in, //! The number of partial derivatives, one entry for //! each dimension const std::array &derivatives, //! The product accumulated for the dimensions which //! have already been handled typename Traits::RangeFieldType prod, //! The number of factors still to go int bound, //! The index of the next entry in the output to fill int& index, //! The wrapper used to access the output vector Access &access) { // start with the highest exponent for this dimension, then work down for (int e = bound; e >= 0; --e) { // the rest of the available exponents, to be used by the other // dimensions int newbound = bound - e; if(e < derivatives[d]) Evaluate:: eval(in, derivatives, 0, newbound, index, access); else { int coeff = 1; for(int i = e - derivatives[d] + 1; i <= e; ++i) coeff *= i; // call the evaluator for the next dimension Evaluate:: eval( // pass the coordinate and the derivatives unchanged in, derivatives, // also pass the product accumulated so far, but also // include the current dimension prod * ipow(in[d], e-derivatives[d]) * coeff, // pass the number of remaining exponents to the next // dimension newbound, // pass the next index to fill and the output access // wrapper index, access); } } } }; /** \copydoc Evaluate * \brief Specializes the end of the recursion * \internal */ template struct Evaluate { enum { d = Traits::dimDomain-1 }; //! \copydoc Evaluate::eval template static void eval (const typename Traits::DomainType &in, const std::array &derivatives, typename Traits::RangeFieldType prod, int bound, int& index, Access &access) { if(bound < derivatives[d]) prod = 0; else { int coeff = 1; for(int i = bound - derivatives[d] + 1; i <= bound; ++i) coeff *= i; prod *= ipow(in[d], bound-derivatives[d]) * coeff; } access[index] = prod; ++index; } }; } //namespace MonomImp /**@ingroup LocalBasisImplementation \brief Constant shape function Defines the constant scalar shape function in d dimensions. Is valid on any type of reference element. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam d Domain dimension \tparam p polynomial order of the shapefunctions \tparam diffOrder Maximum differentiation order to report in the traits. \nosubgrouping */ template class MonomialLocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix,diffOrder> Traits; //! \brief number of shape functions unsigned int size () const { return MonomImp::Size::val; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { DUNE_NO_DEPRECATED_BEGIN evaluate<0>(std::array(), in, out); DUNE_NO_DEPRECATED_END } /** \brief Evaluate partial derivatives of any order of all shape functions * \param order Order of the partial derivatives, in the classic multi-index notation * \param in Position where to evaluate the derivatives * \param[out] out Return value: the desired partial derivatives */ inline void partial(const std::array& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); switch (totalOrder) { case 0: evaluateFunction(in,out); break; case 1: { std::array directions; directions[0] = std::find(order.begin(), order.end(), 1)-order.begin(); DUNE_NO_DEPRECATED_BEGIN evaluate<1>(directions, in, out); DUNE_NO_DEPRECATED_END break; } case 2: { std::array directions; unsigned int counter = 0; auto nonconstOrder = order; // need a copy that I can modify for (unsigned int i=0; i(directions, in, out); DUNE_NO_DEPRECATED_END break; } default: // \todo The 'evaluate' method implements higher derivatives DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! return given derivative of all components template inline void DUNE_DEPRECATED_MSG("Use method 'partial' instead!") evaluate (const std::array& directions, const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); int index = 0; std::array derivatives; for(unsigned int i = 0; i < d; ++i) derivatives[i] = 0; for(unsigned int i = 0; i < k; ++i) ++derivatives[directions[i]]; MonomImp::EvalAccess access(out); for(unsigned int lp = 0; lp <= p; ++lp) MonomImp::Evaluate::eval(in, derivatives, 1, lp, index, access); } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(size()); std::array derivatives; for(unsigned int i = 0; i < d; ++i) derivatives[i] = 0; for(unsigned int i = 0; i < d; ++i) { derivatives[i] = 1; int index = 0; MonomImp::JacobianAccess access(out, i); for(unsigned int lp = 0; lp <= p; ++lp) MonomImp::Evaluate::eval(in, derivatives, 1, lp, index, access); derivatives[i] = 0; } } //! \brief Polynomial order of the shape functions unsigned int order () const { return p; } }; } #endif // DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALBASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/monomial/monomiallocalcoefficients.hh000066400000000000000000000021131313314431100310040ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALCOEFFICIENTS_HH #include #include #include "../common/localkey.hh" namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for monomial finite elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class MonomialLocalCoefficients { public: //! \brief Standard constructor MonomialLocalCoefficients () : index(static_size, LocalKey(0,0,0)) { for(int i = 0; i < static_size; ++i) index[i].index(i); } //! number of coefficients std::size_t size () const { return static_size; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return index[i]; } private: std::vector index; }; } #endif //DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALCOEFFICIENTS_HH dune-localfunctions-2.5.1/dune/localfunctions/monomial/monomiallocalinterpolation.hh000066400000000000000000000052411313314431100312370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALINTERPOLATION_HH #include #include #include #include #include namespace Dune { template class MonomialLocalInterpolation { typedef typename LB::Traits::DomainType D; typedef typename LB::Traits::DomainFieldType DF; static const int dimD=LB::Traits::dimDomain; typedef typename LB::Traits::RangeType R; typedef typename LB::Traits::RangeFieldType RF; typedef QuadratureRule QR; typedef typename QR::iterator QRiterator; public: MonomialLocalInterpolation (const GeometryType >_, const LB &lb_) : gt(gt_), lb(lb_), Minv(0) , qr(QuadratureRules::rule(gt, 2*lb.order())) { // Compute inverse of the mass matrix of the local basis, and store it in Minv if(size != lb.size()) DUNE_THROW(Exception, "size template parameter does not match size of " "local basis"); const QRiterator qrend = qr.end(); for(QRiterator qrit = qr.begin(); qrit != qrend; ++qrit) { std::vector base; lb.evaluateFunction(qrit->position(),base); for(unsigned int i = 0; i < size; ++i) for(unsigned int j = 0; j < size; ++j) Minv[i][j] += qrit->weight() * base[i] * base[j]; } Minv.invert(); } /** \brief Determine coefficients interpolating a given function * * The method computes the coefficients * for the L^2 projection with respect to the given * GeometryType. Be careful: the implementation is * unstable for higher polynomial degrees. */ template void interpolate (const F& f, std::vector& out) const { out.clear(); out.resize(size, 0); const QRiterator qrend = qr.end(); for(QRiterator qrit = qr.begin(); qrit != qrend; ++qrit) { //TODO: mass matrix R y; f.evaluate(qrit->position(),y); std::vector base; lb.evaluateFunction(qrit->position(),base); for(unsigned int i = 0; i < size; ++i) for(unsigned int j = 0; j < size; ++j) out[i] += Minv[i][j] * qrit->weight() * y * base[j]; } } private: GeometryType gt; const LB &lb; FieldMatrix Minv; const QR &qr; }; } #endif //DUNE_LOCALFUNCTIONS_MONOMIAL_MONOMIALLOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/orthonormal.hh000066400000000000000000000036241313314431100243350ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ORTHONORMALFINITEELEMENT_HH #define DUNE_ORTHONORMALFINITEELEMENT_HH #include #include #include #include namespace Dune { /** * \brief A class providing orthonormal basis functions * * These basis functions are constructed by l2 orthonormalizing * of monomials over a reference element. Thus the span is * always Pk. The coefficients and the interpolation are given * by the Dune::DGLocalCoefficientsFactory and the * Dune::LocalL2InterpolationFactory. * * \ingroup Orthonormal * * \tparam dimDomain dimension of reference elements * \tparam D domain for basis functions * \tparam R range for basis functions * \tparam SF storage field for basis matrix * \tparam CF compute field for basis matrix **/ template< unsigned int dimDomain, class D, class R, class SF=R, class CF=SF > class OrthonormalLocalFiniteElement : public GenericLocalFiniteElement< OrthonormalBasisFactory< dimDomain, SF, CF >, DGLocalCoefficientsFactory< OrthonormalBasisFactory< dimDomain, SF, CF > >, LocalL2InterpolationFactory< OrthonormalBasisFactory< dimDomain, SF, CF >,true > > { typedef GenericLocalFiniteElement< OrthonormalBasisFactory< dimDomain, SF, CF >, DGLocalCoefficientsFactory< OrthonormalBasisFactory< dimDomain, SF, CF > >, LocalL2InterpolationFactory< OrthonormalBasisFactory< dimDomain, SF, CF >,true > > Base; public: using typename Base::Traits; /** \todo Please doc me ! */ OrthonormalLocalFiniteElement ( const GeometryType >, unsigned int order ) : Base(gt, order) {} }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/orthonormal/000077500000000000000000000000001313314431100240075ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/orthonormal/CMakeLists.txt000066400000000000000000000002071313314431100265460ustar00rootroot00000000000000install(FILES orthonormalbasis.hh orthonormalcompute.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/orthonormal) dune-localfunctions-2.5.1/dune/localfunctions/orthonormal/orthonormalbasis.hh000066400000000000000000000052611313314431100277220ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ORTHONORMALBASIS_HH #define DUNE_ORTHONORMALBASIS_HH #include #include #include #include namespace Dune { // OrthonormalBasisFactory // ----------------------- template< int dim, class SF, class CF = typename ComputeField< SF, 512 >::Type > struct OrthonormalBasisFactory; template< int dim, class SF, class CF > struct OrthonormalBasisFactoryTraits { typedef Dune::MonomialBasisProvider< dim, SF > MonomialBasisProviderType; typedef typename MonomialBasisProviderType::Object MonomialBasisType; typedef SparseCoeffMatrix< SF, 1 > CoefficientMatrix; typedef StandardEvaluator< MonomialBasisType > Evaluator; typedef PolynomialBasis< Evaluator, CoefficientMatrix > Basis; static const unsigned int dimension = dim; typedef unsigned int Key; typedef const Basis Object; typedef OrthonormalBasisFactory Factory; }; template< int dim, class SF, class CF > struct OrthonormalBasisFactory : public TopologyFactory< OrthonormalBasisFactoryTraits > { static const unsigned int dimension = dim; typedef SF StorageField; typedef CF ComputeField; typedef OrthonormalBasisFactoryTraits Traits; typedef typename Traits::Key Key; typedef typename Traits::Object Object; template struct EvaluationBasisFactory { typedef MonomialBasisProvider Type; }; typedef typename EvaluationBasisFactory< dimension, StorageField >::Type MonomialBasisProviderType; typedef typename MonomialBasisProviderType::Object MonomialBasisType; typedef SparseCoeffMatrix< StorageField, 1 > CoefficientMatrix; typedef StandardEvaluator< MonomialBasisType > Evaluator; typedef PolynomialBasis< Evaluator, CoefficientMatrix > Basis; typedef typename Impl::SimplexTopology< dim >::type SimplexTopology; template< class Topology > static Object *createObject ( const unsigned int order ) { const typename Traits::MonomialBasisType &monomialBasis = *Traits::MonomialBasisProviderType::template create< SimplexTopology >( order ); static typename Traits::CoefficientMatrix _coeffs; if( _coeffs.size() <= monomialBasis.size() ) { ONBCompute::ONBMatrix< Topology, ComputeField > matrix( order ); _coeffs.fill( matrix ); } return new Basis( monomialBasis, _coeffs, monomialBasis.size() ); } }; } #endif // #ifndef DUNE_ORTHONORMALBASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/orthonormal/orthonormalcompute.hh000066400000000000000000000122361313314431100302750ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ORTHONORMALCOMPUTE_HH #define DUNE_ORTHONORMALCOMPUTE_HH #include #include #include #include #include #include #include #include #include #include #include namespace ONBCompute { template< class scalar_t > scalar_t factorial( int start, int end ) { scalar_t ret( 1 ); for( int j = start; j <= end; ++j ) ret *= scalar_t( j ); return ret; } // Integral // -------- template< class Topology > struct Integral; template< class Base > struct Integral< Dune::Impl::Pyramid< Base > > { template< int dim, class scalar_t > static int compute ( const Dune::MultiIndex< dim, scalar_t > &alpha, scalar_t &p, scalar_t &q ) { const int dimension = Base::dimension+1; int i = alpha.z( Base::dimension ); int ord = Integral< Base >::compute( alpha, p, q ); p *= factorial< scalar_t >( 1, i ); q *= factorial< scalar_t >( dimension + ord, dimension + ord + i ); return ord + i; } }; template< class Base > struct Integral< Dune::Impl::Prism< Base > > { template< int dim, class scalar_t > static int compute ( const Dune::MultiIndex< dim, scalar_t > &alpha, scalar_t &p, scalar_t &q ) { int i = alpha.z( Base::dimension ); int ord = Integral< Base >::compute( alpha, p, q ); //Integral< Base >::compute( alpha, p, q ); //p *= scalar_t( 1 ); q *= scalar_t( i+1 ); return ord + i; } }; template<> struct Integral< Dune::Impl::Point > { template< int dim, class scalar_t > static int compute ( const Dune::MultiIndex< dim, scalar_t > &alpha, scalar_t &p, scalar_t &q ) { p = scalar_t( 1 ); q = scalar_t( 1 ); return 0; } }; // ONBMatrix // --------- template< class Topology, class scalar_t > class ONBMatrix : public Dune::LFEMatrix< scalar_t > { typedef ONBMatrix< Topology, scalar_t > This; typedef Dune::LFEMatrix< scalar_t > Base; public: typedef std::vector< scalar_t > vec_t; typedef Dune::LFEMatrix< scalar_t > mat_t; explicit ONBMatrix ( unsigned int order ) { // get all multiindecies for monomial basis const unsigned int dim = Topology::dimension; typedef Dune::MultiIndex< dim, scalar_t > MI; Dune::StandardMonomialBasis< dim, MI > basis( order ); const std::size_t size = basis.size(); std::vector< Dune::FieldVector< MI, 1 > > y( size ); Dune::FieldVector< MI, dim > x; for( unsigned int i = 0; i < dim; ++i ) x[ i ].set( i ); basis.evaluate( x, y ); // set bounds of data Base::resize( size, size ); S.resize( size, size ); d.resize( size ); // setup matrix for bilinear form x^T S y: S_ij = int_A x^(i+j) scalar_t p, q; for( std::size_t i = 0; i < size; ++i ) { for( std::size_t j = 0; j < size; ++j ) { Integral< Topology >::compute( y[ i ][ 0 ] * y[ j ][ 0 ], p, q ); S( i, j ) = p; S( i, j ) /= q; } } // orthonormalize gramSchmidt(); } template< class Vector > void row ( unsigned int row, Vector &vec ) const { // transposed matrix is required assert( row < Base::cols() ); for( std::size_t i = 0; i < Base::rows(); ++i ) Dune::field_cast( Base::operator()( i, row ), vec[ i ] ); } private: void sprod ( int col1, int col2, scalar_t &ret ) { ret = 0; for( int k = 0; k <= col1; ++k ) { for( int l = 0; l <=col2; ++l ) ret += Base::operator()( l, col2 ) * S( l, k ) * Base::operator()( k, col1 ); } } void vmul ( std::size_t col, std::size_t rowEnd, const scalar_t &s ) { for( std::size_t i = 0; i <= rowEnd; ++i ) Base::operator()( i, col ) *= s; } void vsub ( std::size_t coldest, std::size_t colsrc, std::size_t rowEnd, const scalar_t &s ) { for( std::size_t i = 0; i <= rowEnd; ++i ) Base::operator()( i, coldest ) -= s * Base::operator()( i, colsrc ); } void gramSchmidt () { // setup identity const std::size_t N = Base::rows(); for( std::size_t i = 0; i < N; ++i ) { for( std::size_t j = 0; j < N; ++j ) Base::operator()( i, j ) = scalar_t( i == j ? 1 : 0 ); } // perform Gram-Schmidt procedure scalar_t s; sprod( 0, 0, s ); vmul( 0, 0, scalar_t( 1 ) / sqrt( s ) ); for( std::size_t i = 1; i < N; ++i ) { for( std::size_t k = 0; k < i; ++k ) { sprod( i, k, s ); vsub( i, k, i, s ); } sprod( i, i, s ); vmul( i, i, scalar_t( 1 ) / sqrt( s ) ); } } vec_t d; mat_t S; }; } // namespace ONBCompute #endif // #ifndef DUNE_ORTHONORMALCOMPUTE_HH dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek.hh000066400000000000000000000004161313314431100250010ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file \brief Convenience header that includes all available Rannacher-Turek LocalFiniteElements */ #include dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/000077500000000000000000000000001313314431100244575ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/CMakeLists.txt000066400000000000000000000004721313314431100272220ustar00rootroot00000000000000add_subdirectory(rannacherturek2d) add_subdirectory(rannacherturek3d) install(FILES ${rannacherturek_HEADERS} rannacherturek.hh rannachertureklocalbasis.hh rannachertureklocalcoefficients.hh rannachertureklocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/rannacherturek) dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannacherturek.hh000066400000000000000000000040061313314431100300140ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RANNACHER_TUREK_LOCALFINITEELEMENT_HH #define DUNE_RANNACHER_TUREK_LOCALFINITEELEMENT_HH #include #include #include "rannachertureklocalbasis.hh" #include "rannachertureklocalcoefficients.hh" #include "rannachertureklocalinterpolation.hh" namespace Dune { /** * \brief Rannacher-Turek shape functions. * * \ingroup RannacherTurek * * \tparam D type to represent the field in the domain. * \tparam R type to represent the field in the range. * \tparam d domain dimension */ template< class D, class R, unsigned int d > struct RannacherTurekLocalFiniteElement { //! \brief export traits class typedef LocalFiniteElementTraits< RannacherTurekLocalBasis< D, R, d >, RannacherTurekLocalCoefficients< d >, RannacherTurekLocalInterpolation< D, R, d > > Traits; //! \brief return local basis const typename Traits::LocalBasisType &localBasis () const { return localBasis_; } //! \brief return local coefficients const typename Traits::LocalCoefficientsType &localCoefficients () const { return localCoefficients_; } //! \brief return local interpolation const typename Traits::LocalInterpolationType &localInterpolation () const { return localInterpolation_; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return localBasis_.size(); } //! \brief return geometry type GeometryType type () const { return GeometryType( typename Impl::CubeTopology< d >::type() ); } private: typename Traits::LocalBasisType localBasis_; typename Traits::LocalCoefficientsType localCoefficients_; typename Traits::LocalInterpolationType localInterpolation_; }; } // namespace Dune #endif // #ifndef DUNE_RANNACHER_TUREK_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannacherturek2d/000077500000000000000000000000001313314431100277215ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannacherturek2d/CMakeLists.txt000066400000000000000000000002151313314431100324570ustar00rootroot00000000000000install(FILES rannacherturek2dlocalbasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/rannacherturek/rannacherturek2d) rannacherturek2dlocalbasis.hh000066400000000000000000000073221313314431100354660ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannacherturek2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RANNACHER_TUREK_2D_LOCALBASIS_HH #define DUNE_RANNACHER_TUREK_2D_LOCALBASIS_HH #include #include #include #include #include namespace Dune { template< class D, class R > struct RannacherTurek2DLocalBasis { typedef LocalBasisTraits< D, 2, FieldVector< D, 2 >, R, 1, FieldVector< R, 1 >, FieldMatrix< R, 1, 2 > > Traits; //! \brief number of shape functions unsigned int size () const { return 4; } //! \brief evaluate all shape functions inline void evaluateFunction ( const typename Traits::DomainType &in, std::vector< typename Traits::RangeType > &out ) const { out.resize(4); typename Traits::DomainFieldType qbase = in[0]*in[0]-in[1]*in[1]; out[0] = .75 - 2*in[0] + in[1] + qbase; out[1] = -.25 + in[1] + qbase; out[2] = .75 + in[0] - 2*in[1] - qbase; out[3] = -.25 + in[0] - qbase; } //! \brief evaluate jacobian of all shape functions inline void evaluateJacobian ( const typename Traits::DomainType &in, std::vector< typename Traits::JacobianType > &out ) const { out.resize(4); // see http://www.dune-project.org/doc/doxygen/html/classDune_1_1C1LocalBasisInterface.html#d6f8368f8aa43439cc7ef10419f6e2ea // out[i][j][k] = d_k \phi^i_j , where \phi^i_j is the j'th component of the i'th shape function. out[0][0][0] = -2 + 2*in[0]; out[0][0][1] = 1 - 2*in[1]; out[1][0][0] = 2*in[0]; out[1][0][1] = 1 - 2*in[1]; out[2][0][0] = 1 - 2*in[0]; out[2][0][1] = -2 + 2*in[1]; out[3][0][0] = 1 - 2*in[0]; out[3][0][1] = 2*in[1]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); switch (direction) { case 0: out[0] = -2 + 2*in[0]; out[1] = 2*in[0]; out[2] = 1 - 2*in[0]; out[3] = 1 - 2*in[0]; break; case 1: out[0] = 1 - 2*in[1]; out[1] = 1 - 2*in[1]; out[2] = -2 + 2*in[1]; out[3] = 2*in[1]; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else if (totalOrder == 2) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 2)); out.resize(size()); switch (direction) { case 0: out[0] = out[1] = 2; out[2] = out[3] =-2; break; case 1: out[0] = out[1] =-2; out[2] = out[3] = 2; break; default: out[0] = out[1] = out[2] = out[3] = 0; break; } } else { out[0] = out[1] = out[2] = out[3] = 0; } } //! \brief polynomial order of the shape functions unsigned int order () const { // must be 2 here since it contains x^2 and x^2 return 2; } }; } //namespace Dune #endif // #ifndef DUNE_RANNACHER_TUREK_2D_LOCALBASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannacherturek3d/000077500000000000000000000000001313314431100277225ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannacherturek3d/CMakeLists.txt000066400000000000000000000002151313314431100324600ustar00rootroot00000000000000install(FILES rannacherturek3dlocalbasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/rannacherturek/rannacherturek3d) rannacherturek3dlocalbasis.hh000066400000000000000000000104311313314431100354630ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannacherturek3d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RANNACHER_TUREK_3D_LOCALBASIS_HH #define DUNE_RANNACHER_TUREK_3D_LOCALBASIS_HH #include #include #include #include #include namespace Dune { template< class D, class R > class RannacherTurek3DLocalBasis { static const int coefficients[ 6 ][ 6 ]; public: typedef LocalBasisTraits< D, 3, FieldVector< D, 3 >, R, 1, FieldVector< R, 1 >, FieldMatrix< R, 1, 3 > > Traits; //! \brief number of shape functions unsigned int size () const { return 6; } //! \brief evaluate all shape functions inline void evaluateFunction ( const typename Traits::DomainType &in, std::vector< typename Traits::RangeType > &out ) const { typedef typename Traits::RangeFieldType RangeFieldType; RangeFieldType y[ 6 ] = { 1, in[ 0 ], in[ 1 ], in[ 2 ], in[ 0 ]*in[ 0 ] - in[ 1 ]*in[ 1 ], in[ 1 ]*in[ 1 ] - in[ 2 ]*in[ 2 ] }; out.resize( size() ); for( unsigned int i = 0; i < size(); ++i ) { out[ i ] = RangeFieldType( 0 ); for( unsigned int j = 0; j < 6; ++j ) out[ i ] += coefficients[ i ][ j ]*y[ j ]; out[ i ] /= RangeFieldType( 3 ); } } //! \brief evaluate jacobian of all shape functions inline void evaluateJacobian ( const typename Traits::DomainType &in, std::vector< typename Traits::JacobianType > &out ) const { typedef typename Traits::RangeFieldType RangeFieldType; RangeFieldType y0[ 5 ] = { 1, 0, 0, 2*in[ 0 ], 0 }; RangeFieldType y1[ 5 ] = { 0, 1, 0, -2*in[ 1 ], 2*in[ 1 ] }; RangeFieldType y2[ 5 ] = { 0, 0, 1, 0, -2*in[ 2 ] }; out.resize( size() ); for( unsigned int i = 0; i < size(); ++i ) { out[ i ] = RangeFieldType( 0 ); for( unsigned int j = 0; j < 5; ++j ) { out[ i ][ 0 ][ 0 ] += coefficients[ i ][ j+1 ]*y0[ j ]; out[ i ][ 0 ][ 1 ] += coefficients[ i ][ j+1 ]*y1[ j ]; out[ i ][ 0 ][ 2 ] += coefficients[ i ][ j+1 ]*y2[ j ]; } out[ i ] /= RangeFieldType( 3 ); } } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); using RangeFieldType = typename Traits::RangeFieldType; RangeFieldType y[3][5] = { { 1.0, 0.0, 0.0, 2*in[0], 0.0 }, { 0.0, 1.0, 0.0, -2*in[1], 2*in[1] }, { 0.0, 0.0, 1.0, 0.0, -2*in[2] } }; for (std::size_t i = 0; i < size(); ++i) { out[i] = RangeFieldType{0}; for (std::size_t j = 0; j < 5; ++j) out[i] += coefficients[i][j+1] * y[direction][j]; out[i] /= RangeFieldType{3}; } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief polynomial order of the shape functions unsigned int order () const { return 2; } }; // RannacherTurek3DLocalBasis::coefficients // ---------------------------------------- template< class D, class R > const int RannacherTurek3DLocalBasis< D, R > ::coefficients[ 6 ][ 6 ] = {{ 2, -7, 2, 2, 4, 2 }, { -1, -1, 2, 2, 4, 2 }, { 2, 2, -7, 2, -2, 2 }, { -1, 2, -1, 2, -2, 2 }, { 2, 2, 2, -7, -2, -4 }, { -1, 2, 2, -1, -2, -4 }}; } //namespace Dune #endif // #ifndef DUNE_RANNACHER_TUREK_3D_LOCALBASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannachertureklocalbasis.hh000066400000000000000000000017441313314431100320570ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RANNACHER_TUREK_LOCALBASIS_HH #define DUNE_RANNACHER_TUREK_LOCALBASIS_HH #include "rannacherturek2d/rannacherturek2dlocalbasis.hh" #include "rannacherturek3d/rannacherturek3dlocalbasis.hh" namespace Dune { /**@ingroup LocalBasisImplementation \brief Rannacher-Turek shape functions \tparam D type to represent the field in the domain. \tparam R type to represent the field in the range. \tparam d domain dimension \nosubgrouping */ template< class D, class R, unsigned int d > struct RannacherTurekLocalBasis; template< class D, class R > struct RannacherTurekLocalBasis< D, R, 2 > : public RannacherTurek2DLocalBasis< D, R > {}; template< class D, class R > struct RannacherTurekLocalBasis< D, R, 3 > : public RannacherTurek3DLocalBasis< D, R > {}; } // namespace Dune #endif // #ifndef DUNE_RANNACHER_TUREK_LOCALBASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannachertureklocalcoefficients.hh000066400000000000000000000026461313314431100334210ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RANNACHER_TUREK_LOCALCOEFFICIENTS_HH #define DUNE_RANNACHER_TUREK_LOCALCOEFFICIENTS_HH #include #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief layout for Rannacher-Turek elements \tparam d Domain dimension \nosubgrouping */ template< unsigned int d > struct RannacherTurekLocalCoefficients { RannacherTurekLocalCoefficients () { for( std::size_t i = 0; i < 2*d; ++i ) localKeys_[ i ] = LocalKey( i, 1, 0 ); } RannacherTurekLocalCoefficients ( const RannacherTurekLocalCoefficients &other ) { (*this) = other; } RannacherTurekLocalCoefficients &operator= ( const RannacherTurekLocalCoefficients &other ) { std::copy( other.localKeys_.begin(), other.localKeys_.end(), localKeys_.begin() ); return *this; } //! number of coefficients std::size_t size () const { return 2*d; } //! map index i to local key const LocalKey &localKey ( std::size_t i ) const { assert( 0 <= i && i < 2*d ); return localKeys_[ i ]; } private: std::array< LocalKey, 2*d > localKeys_; }; } // namespace Dune #endif // #ifndef DUNE_RANNACHER_TUREK_LOCALCOEFFICIENTS_HH dune-localfunctions-2.5.1/dune/localfunctions/rannacherturek/rannachertureklocalinterpolation.hh000066400000000000000000000031501313314431100336360ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RANNACHER_TUREK_LOCALINTERPOLATION_HH #define DUNE_RANNACHER_TUREK_LOCALINTERPOLATION_HH #include #include #include #include #include namespace Dune { /** \brief please doc me \tparam D type to represent the field in the domain. \tparam R type to represent the field in the range. \tparam d domain dimension */ template< class D, class R, unsigned int d > class RannacherTurekLocalInterpolation { typedef LocalBasisTraits< D, d, FieldVector< D, d >, R, 1, FieldVector< R, 1 >, FieldMatrix< R, 1, d > > Traits; public: template< class F, class C > void interpolate ( const F &f, std::vector< C > &out ) const { typedef typename Traits::DomainType DomainType; typedef typename Traits::RangeType RangeType; // get cubic reference element const ReferenceElement< D, d > &referenceElement = ReferenceElements< D, d >::cube(); const int size = 2*d; assert( size == referenceElement.size( 1 ) ); // resize vector out.resize( size ); // evaluate local function in barycenter of codim 1 subentities for( int i = 0; i < size; ++i ) { const DomainType &x = referenceElement.position( i, 1 ); RangeType y; f.evaluate( x, y ); out[ i ] = y; } } }; } // namespace Dune #endif // #ifndef DUNE_RANNACHER_TUREK_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas.hh000066400000000000000000000005651313314431100246560ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RAVIARTTHOMASFINITEELEMENT_HH #define DUNE_RAVIARTTHOMASFINITEELEMENT_HH #include #include #endif // #ifndef DUNE_RAVIARTTHOMASFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/000077500000000000000000000000001313314431100243275ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/CMakeLists.txt000066400000000000000000000013551313314431100270730ustar00rootroot00000000000000add_subdirectory(raviartthomas02d) add_subdirectory(raviartthomas0cube2d) add_subdirectory(raviartthomas0cube3d) add_subdirectory(raviartthomas12d) add_subdirectory(raviartthomas1cube2d) add_subdirectory(raviartthomas1cube3d) add_subdirectory(raviartthomas2cube2d) add_subdirectory(raviartthomas3cube2d) add_subdirectory(raviartthomas4cube2d) add_subdirectory(raviartthomassimplex) install(FILES raviartthomas02d.hh raviartthomas0cube2d.hh raviartthomas0cube3d.hh raviartthomas12d.hh raviartthomas1cube2d.hh raviartthomas1cube3d.hh raviartthomas2cube2d.hh raviartthomas3cube2d.hh raviartthomas4cube2d.hh raviartthomascube.hh raviartthomassimplex.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas) dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas02d.hh000066400000000000000000000035171313314431100300500ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RAVIARTTHOMAS02DLOCALFINITEELEMENT_HH #define DUNE_RAVIARTTHOMAS02DLOCALFINITEELEMENT_HH #include #include #include "raviartthomas02d/raviartthomas02dlocalbasis.hh" #include "raviartthomas02d/raviartthomas02dlocalcoefficients.hh" #include "raviartthomas02d/raviartthomas02dlocalinterpolation.hh" namespace Dune { /** * \brief Zero order Raviart-Thomas shape functions on triangles. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT02DLocalFiniteElement { public: typedef LocalFiniteElementTraits,RT02DLocalCoefficients, RT02DLocalInterpolation > > Traits; //! \brief Standard constructor RT02DLocalFiniteElement () { gt.makeTriangle(); } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT02DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeTriangle(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } GeometryType type () const { return gt; } private: RT02DLocalBasis basis; RT02DLocalCoefficients coefficients; RT02DLocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas02d/000077500000000000000000000000001313314431100275215ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas02d/CMakeLists.txt000066400000000000000000000003331313314431100322600ustar00rootroot00000000000000install(FILES raviartthomas02dlocalbasis.hh raviartthomas02dlocalcoefficients.hh raviartthomas02dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas02d) raviartthomas02dlocalbasis.hh000066400000000000000000000065311313314431100352170ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas02d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RT0TRIANGLELOCALBASIS_HH #define DUNE_RT0TRIANGLELOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lowest order Raviart-Thomas shape functions on the reference triangle. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class RT02DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT02DLocalBasis () { sign0 = sign1 = sign2 = 1.0; } //! \brief Make set numer s, where 0<=s<8 RT02DLocalBasis (unsigned int s) { sign0 = sign1 = sign2 = 1.0; if (s&1) sign0 = -1.0; if (s&2) sign1 = -1.0; if (s&4) sign2 = -1.0; } //! \brief number of shape functions unsigned int size () const { return 3; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(3); out[0][0] = sign0*in[0]; out[0][1]=sign0*(in[1]-D(1)); out[1][0] = sign1*(in[0]-D(1)); out[1][1]=sign1*in[1]; out[2][0] = sign2*in[0]; out[2][1]=sign2*in[1]; } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(3); out[0][0][0] = sign0; out[0][0][1] = 0; out[0][1][0] = 0; out[0][1][1] = sign0; out[1][0][0] = sign1; out[1][0][1] = 0; out[1][1][0] = 0; out[1][1][1] = sign1; out[2][0][0] = sign2; out[2][0][1] = 0; out[2][1][0] = 0; out[2][1][1] = sign2; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); out[0][direction] = sign0; out[0][1-direction] = 0; out[1][direction] = sign1; out[1][1-direction] = 0; out[2][direction] = sign2; out[2][1-direction] = 0; } else { out.resize(size()); for (std::size_t i = 0; i < size(); ++i) for (std::size_t j = 0; j < 2; ++j) out[i][j] = 0; } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 1; } private: R sign0, sign1, sign2; }; } #endif raviartthomas02dlocalcoefficients.hh000066400000000000000000000016521313314431100365560ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas02d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RT0TRIANGLELOCALCOEFFICIENTS_HH #define DUNE_RT0TRIANGLELOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for RT0 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class RT02DLocalCoefficients { public: //! \brief Standard constructor RT02DLocalCoefficients () : li(3) { for (std::size_t i=0; i<3; i++) li[i] = LocalKey(i,1,0); } //! number of coefficients std::size_t size () const { return 3; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif raviartthomas02dlocalinterpolation.hh000066400000000000000000000032211313314431100367760ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas02d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RT02DLOCALINTERPOLATION_HH #define DUNE_RT02DLOCALINTERPOLATION_HH #include #include #include namespace Dune { template class RT02DLocalInterpolation { public: //! \brief Standard constructor RT02DLocalInterpolation () { sign0 = sign1 = sign2 = 1.0; } //! \brief Make set numer s, where 0<=s<8 RT02DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = 1.0; if (s&1) sign0 *= -1.0; if (s&2) sign1 *= -1.0; if (s&4) sign2 *= -1.0; m0[0] = 0.5; m0[1] = 0.0; m1[0] = 0.0; m1[1] = 0.5; m2[0] = 0.5; m2[1] = 0.5; n0[0] = 0.0; n0[1] = -1.0; n1[0] = -1.0; n1[1] = 0.0; n2[0] = 1.0/sqrt(2.0); n2[1] = 1.0/sqrt(2.0); c0 = ( 0.5*n0[0] - 1.0*n0[1]); c1 = (-1.0*n1[0] + 0.5*n1[1]); c2 = ( 0.5*n2[0] + 0.5*n2[1]); } template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typename F::Traits::RangeType y; out.resize(3); f.evaluate(m0,y); out[0] = (y[0]*n0[0]+y[1]*n0[1])*sign0/c0; f.evaluate(m1,y); out[1] = (y[0]*n1[0]+y[1]*n1[1])*sign1/c1; f.evaluate(m2,y); out[2] = (y[0]*n2[0]+y[1]*n2[1])*sign2/c2; } private: typename LB::Traits::RangeFieldType sign0,sign1,sign2; typename LB::Traits::DomainType m0,m1,m2; typename LB::Traits::DomainType n0,n1,n2; typename LB::Traits::RangeFieldType c0,c1,c2; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas0cube2d.hh000066400000000000000000000035601313314431100307050ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE2D_LOCALFINITEELEMENT_HH #include #include #include "raviartthomas0cube2d/raviartthomas0cube2dall.hh" namespace Dune { /** * \brief Zero order Raviart-Thomas shape functions on rectangles. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT0Cube2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< RT0Cube2DLocalBasis, RT0Cube2DLocalCoefficients, RT0Cube2DLocalInterpolation > > Traits; RT0Cube2DLocalFiniteElement () { gt.makeQuadrilateral(); } RT0Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeQuadrilateral(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: RT0Cube2DLocalBasis basis; RT0Cube2DLocalCoefficients coefficients; RT0Cube2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas0cube2d/000077500000000000000000000000001313314431100303605ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas0cube2d/CMakeLists.txt000066400000000000000000000002151313314431100331160ustar00rootroot00000000000000install(FILES raviartthomas0cube2dall.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas0cube2d) raviartthomas0cube2dall.hh000066400000000000000000000141711313314431100353500ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas0cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE2D_ALL_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE2D_ALL_HH #include #include #include #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lowest order Raviart-Thomas shape functions on the reference quadrilateral. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class RT0Cube2DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT0Cube2DLocalBasis () { sign0 = sign1 = sign2 = sign3 = 1.0; } //! \brief Make set numer s, where 0<=s<16 RT0Cube2DLocalBasis (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s&1) sign0 = -1.0; if (s&2) sign1 = -1.0; if (s&4) sign2 = -1.0; if (s&8) sign3 = -1.0; } //! \brief number of shape functions unsigned int size () const { return 4; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(4); out[0][0] = sign0*(in[0]-1.0); out[0][1]=0.0; out[1][0] = sign1*(in[0]); out[1][1]=0.0; out[2][0] = 0.0; out[2][1]=sign2*(in[1]-1.0); out[3][0] = 0.0; out[3][1]=sign3*(in[1]); } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(4); out[0][0][0] = sign0; out[0][0][1] = 0; out[0][1][0] = 0; out[0][1][1] = 0; out[1][0][0] = sign1; out[1][0][1] = 0; out[1][1][0] = 0; out[1][1][1] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][1][0] = 0; out[2][1][1] = sign2; out[3][0][0] = 0; out[3][0][1] = 0; out[3][1][0] = 0; out[3][1][1] = sign3; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i][0] = out[i][1] = 0; switch (direction) { case 0: out[0][0] = sign0; out[1][0] = sign1; break; case 1: out[2][1] = sign2; out[3][1] = sign3; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { out.resize(size()); for (std::size_t i = 0; i < size(); ++i) for (std::size_t j = 0; j < 2; ++j) out[i][j] = 0; } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 1; } private: R sign0, sign1, sign2, sign3; }; /**@ingroup LocalInterpolationImplementation \brief Lowest order Raviart-Thomas shape functions on the reference quadrilateral. \tparam LB corresponding LocalBasis giving traits \nosubgrouping */ template class RT0Cube2DLocalInterpolation { public: //! \brief Standard constructor RT0Cube2DLocalInterpolation () { sign0 = sign1 = sign2 = sign3 = 1.0; } //! \brief Make set numer s, where 0<=s<8 RT0Cube2DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s&1) sign0 *= -1.0; if (s&2) sign1 *= -1.0; if (s&4) sign2 *= -1.0; if (s&8) sign3 *= -1.0; m0[0] = 0.0; m0[1] = 0.5; m1[0] = 1.0; m1[1] = 0.5; m2[0] = 0.5; m2[1] = 0.0; m3[0] = 0.5; m3[1] = 1.0; n0[0] = -1.0; n0[1] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n3[0] = 0.0; n3[1] = 1.0; } template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typename F::Traits::RangeType y; out.resize(4); f.evaluate(m0,y); out[0] = (y[0]*n0[0]+y[1]*n0[1])*sign0; f.evaluate(m1,y); out[1] = (y[0]*n1[0]+y[1]*n1[1])*sign1; f.evaluate(m2,y); out[2] = (y[0]*n2[0]+y[1]*n2[1])*sign2; f.evaluate(m3,y); out[3] = (y[0]*n3[0]+y[1]*n3[1])*sign3; } private: typename LB::Traits::RangeFieldType sign0,sign1,sign2,sign3; typename LB::Traits::DomainType m0,m1,m2,m3; typename LB::Traits::DomainType n0,n1,n2,n3; }; /**@ingroup LocalLayoutImplementation \brief Layout map for RT0 elements on quadrilaterals \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class RT0Cube2DLocalCoefficients { public: //! \brief Standard constructor RT0Cube2DLocalCoefficients () : li(4) { for (std::size_t i=0; i<4; i++) li[i] = LocalKey(i,1,0); } //! number of coefficients std::size_t size () const { return 4; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE2D_ALL_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas0cube3d.hh000066400000000000000000000035451313314431100307110ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE3D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE3D_LOCALFINITEELEMENT_HH #include #include #include "raviartthomas0cube3d/raviartthomas0cube3dall.hh" namespace Dune { /** * \brief Zero order Raviart-Thomas shape functions on cubes. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT0Cube3DLocalFiniteElement { public: typedef LocalFiniteElementTraits< RT0Cube3DLocalBasis, RT0Cube3DLocalCoefficients, RT0Cube3DLocalInterpolation > > Traits; RT0Cube3DLocalFiniteElement () { gt.makeHexahedron(); } RT0Cube3DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeHexahedron(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: RT0Cube3DLocalBasis basis; RT0Cube3DLocalCoefficients coefficients; RT0Cube3DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE3D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas0cube3d/000077500000000000000000000000001313314431100303615ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas0cube3d/CMakeLists.txt000066400000000000000000000002151313314431100331170ustar00rootroot00000000000000install(FILES raviartthomas0cube3dall.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas0cube3d) raviartthomas0cube3dall.hh000066400000000000000000000201331313314431100353450ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas0cube3d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE3D_ALL_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE3D_ALL_HH #include #include #include #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lowest order Raviart-Thomas shape functions on the reference hexahedron. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class RT0Cube3DLocalBasis { public: typedef LocalBasisTraits,R,3,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT0Cube3DLocalBasis () { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; } //! \brief Make set numer s, where 0<=s<64 RT0Cube3DLocalBasis (unsigned int s) { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; if (s&1) sign0 = -1.0; if (s&2) sign1 = -1.0; if (s&4) sign2 = -1.0; if (s&8) sign3 = -1.0; if (s&16) sign4 = -1.0; if (s&32) sign5 = -1.0; } //! \brief number of shape functions unsigned int size () const { return 6; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(6); out[0][0] = sign0*(in[0]-1.0); out[0][1]=0.0; out[0][2]=0.0; out[1][0] = sign1*(in[0]); out[1][1]=0.0; out[1][2]=0.0; out[2][0] = 0.0; out[2][1]=sign2*(in[1]-1.0); out[2][2]=0.0; out[3][0] = 0.0; out[3][1]=sign3*(in[1]); out[3][2]=0.0; out[4][0] = 0.0; out[4][1]=0.0; out[4][2]=sign4*(in[2]-1.0); out[5][0] = 0.0; out[5][1]=0.0; out[5][2]=sign5*(in[2]); } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(6); out[0][0][0] = sign0; out[0][0][1] = 0; out[0][0][2] = 0; out[0][1][0] = 0; out[0][1][1] = 0; out[0][1][2] = 0; out[0][2][0] = 0; out[0][2][1] = 0; out[0][2][2] = 0; out[1][0][0] = sign1; out[1][0][1] = 0; out[1][0][2] = 0; out[1][1][0] = 0; out[1][1][1] = 0; out[1][1][2] = 0; out[1][2][0] = 0; out[1][2][1] = 0; out[1][2][2] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[2][1][0] = 0; out[2][1][1] = sign2; out[2][1][2] = 0; out[2][2][0] = 0; out[2][2][1] = 0; out[2][2][2] = 0; out[3][0][0] = 0; out[3][0][1] = 0; out[3][0][2] = 0; out[3][1][0] = 0; out[3][1][1] = sign3; out[3][1][2] = 0; out[3][2][0] = 0; out[3][2][1] = 0; out[3][2][2] = 0; out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 0; out[4][1][0] = 0; out[4][1][1] = 0; out[4][1][2] = 0; out[4][2][0] = 0; out[4][2][1] = 0; out[4][2][2] = sign4; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[5][1][0] = 0; out[5][1][1] = 0; out[5][1][2] = 0; out[5][2][0] = 0; out[5][2][1] = 0; out[5][2][2] = sign5; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i][0] = out[i][1] = out[i][2] = 0; switch (direction) { case 0: out[0][0] = sign0; out[1][0] = sign1; break; case 1: out[2][1] = sign2; out[3][1] = sign3; break; case 2: out[4][2] = sign4; out[5][2] = sign5; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { out.resize(size()); for (std::size_t i = 0; i < size(); ++i) for (std::size_t j = 0; j < 2; ++j) out[i][j] = 0; } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 1; } private: R sign0, sign1, sign2, sign3, sign4, sign5; }; /**@ingroup LocalInterpolationImplementation \brief Lowest order Raviart-Thomas shape functions on the reference hexahedron. \tparam LB corresponding LocalBasis giving traits \nosubgrouping */ template class RT0Cube3DLocalInterpolation { public: //! \brief Standard constructor RT0Cube3DLocalInterpolation () { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; } //! \brief Make set numer s, where 0<=s<64 RT0Cube3DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; if (s&1) sign0 *= -1.0; if (s&2) sign1 *= -1.0; if (s&4) sign2 *= -1.0; if (s&8) sign3 *= -1.0; if (s&16) sign4 *= -1.0; if (s&32) sign5 *= -1.0; m0[0] = 0.0; m0[1] = 0.5; m0[2] = 0.5; m1[0] = 1.0; m1[1] = 0.5; m1[2] = 0.5; m2[0] = 0.5; m2[1] = 0.0; m2[2] = 0.5; m3[0] = 0.5; m3[1] = 1.0; m3[2] = 0.5; m4[0] = 0.5; m4[1] = 0.5; m4[2] = 0.0; m5[0] = 0.5; m5[1] = 0.5; m5[2] = 1.0; n0[0] = -1.0; n0[1] = 0.0; n0[2] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n1[2] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n2[2] = 0.0; n3[0] = 0.0; n3[1] = 1.0; n3[2] = 0.0; n4[0] = 0.0; n4[1] = 0.0; n4[2] =-1.0; n5[0] = 0.0; n5[1] = 0.0; n5[2] = 1.0; } template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typename F::Traits::RangeType y; out.resize(6); f.evaluate(m0,y); out[0] = (y[0]*n0[0]+y[1]*n0[1]+y[2]*n0[2])*sign0; f.evaluate(m1,y); out[1] = (y[0]*n1[0]+y[1]*n1[1]+y[2]*n1[2])*sign1; f.evaluate(m2,y); out[2] = (y[0]*n2[0]+y[1]*n2[1]+y[2]*n2[2])*sign2; f.evaluate(m3,y); out[3] = (y[0]*n3[0]+y[1]*n3[1]+y[2]*n3[2])*sign3; f.evaluate(m4,y); out[4] = (y[0]*n4[0]+y[1]*n4[1]+y[2]*n4[2])*sign4; f.evaluate(m5,y); out[5] = (y[0]*n5[0]+y[1]*n5[1]+y[2]*n5[2])*sign5; } private: typename LB::Traits::RangeFieldType sign0,sign1,sign2,sign3,sign4,sign5; typename LB::Traits::DomainType m0,m1,m2,m3,m4,m5; typename LB::Traits::DomainType n0,n1,n2,n3,n4,n5; }; /**@ingroup LocalLayoutImplementation \brief Layout map for RT0 elements on quadrilaterals \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class RT0Cube3DLocalCoefficients { public: //! \brief Standard constructor RT0Cube3DLocalCoefficients () : li(6) { for (std::size_t i=0; i<6; i++) li[i] = LocalKey(i,1,0); } //! number of coefficients std::size_t size () const { return 6; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE3D_ALL_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas12d.hh000066400000000000000000000040441313314431100300450ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "raviartthomas12d/raviartthomas12dlocalbasis.hh" #include "raviartthomas12d/raviartthomas12dlocalcoefficients.hh" #include "raviartthomas12d/raviartthomas12dlocalinterpolation.hh" namespace Dune { /** * \brief First order Raviart-Thomas shape functions on triangles. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT12DLocalFiniteElement { public: typedef LocalFiniteElementTraits,RT12DLocalCoefficients, RT12DLocalInterpolation > > Traits; //! \brief Standard constructor RT12DLocalFiniteElement () { gt.makeTriangle(); } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT12DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeTriangle(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: RT12DLocalBasis basis; RT12DLocalCoefficients coefficients; RT12DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas12d/000077500000000000000000000000001313314431100275225ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas12d/CMakeLists.txt000066400000000000000000000003331313314431100322610ustar00rootroot00000000000000install(FILES raviartthomas12dlocalbasis.hh raviartthomas12dlocalcoefficients.hh raviartthomas12dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas12d) raviartthomas12dlocalbasis.hh000066400000000000000000000156441313314431100352260ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas12d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALBASIS_HH #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * @ingroup LocalBasisImplementation * \brief First order Raviart-Thomas shape functions on the reference triangle. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class RT12DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT12DLocalBasis () { sign0 = sign1 = sign2 = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT12DLocalBasis (unsigned int s) { sign0 = sign1 = sign2 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } } //! \brief number of shape functions unsigned int size () const { return 8; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(8); out[0][0] = sign0*(in[0] - 4.0*in[0]*in[1]); out[0][1] = sign0*(-1.0 + 5.0*in[1] - 4.0*in[1]*in[1]); out[1][0] = sign1*(-1.0 + 5.0*in[0] - 4.0*in[0]*in[0]); out[1][1] = sign1*(in[1] - 4.0*in[0]*in[1]); out[2][0] = sign2*(-3.0*in[0] + 4.0*in[0]*in[0] + 4.0*in[1]*in[0]); out[2][1] = sign2*(-3.0*in[1] + 4.0*in[0]*in[1] + 4.0*in[1]*in[1]); out[3][0] = -5.0*in[0] + 8.0*in[0]*in[0] + 4.0*in[1]*in[0]; out[3][1] = 3.0 - 6.0*in[0] - 7.0*in[1] + 8.0*in[0]*in[1] + 4.0*in[1]*in[1]; out[4][0] = -3.0 + 7.0*in[0] + 6.0*in[1] - 4.0*in[0]*in[0] - 8.0*in[1]*in[0]; out[4][1] = 5.0*in[1] - 4.0*in[0]*in[1] - 8.0*in[1]*in[1]; out[5][0] = in[0] - 4.0*in[0]*in[0] + 4.0*in[1]*in[0]; out[5][1] = -1.0*in[1] - 4.0*in[0]*in[1] + 4.0*in[1]*in[1]; out[6][0] = 16.0*in[0] - 16.0*in[0]*in[0] - 8.0*in[1]*in[0]; out[6][1] = 8.0*in[1] - 16.0*in[0]*in[1] - 8.0*in[1]*in[1]; out[7][0] = 8.0*in[0] - 8.0*in[0]*in[0] - 16.0*in[1]*in[0]; out[7][1] = 16.0*in[1] - 8.0*in[0]*in[1] - 16.0*in[1]*in[1]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const typename Traits::DomainType& in, std::vector& out) const { out.resize(8); out[0][0][0] = sign0*(1.0 - 4.0*in[1]); out[0][0][1] = sign0*(-4.0*in[0]); out[0][1][0] = 0.0; out[0][1][1] = sign0*(5.0 - 8.0*in[1]); out[1][0][0] = sign1*(5.0 - 8.0*in[0]); out[1][0][1] = 0.0; out[1][1][0] = sign1*(-4.0*in[1]); out[1][1][1] = sign1*(1.0 - 4.0*in[0]); out[2][0][0] = sign2*(-3.0 + 8.0*in[0] + 4.0*in[1]); out[2][0][1] = sign2*(4.0*in[0]); out[2][1][0] = sign2*(4.0*in[1]); out[2][1][1] = sign2*(-3.0 + 4.0*in[0] + 8.0*in[1]); out[3][0][0] = -5.0 + 16.0*in[0] + 4.0*in[1]; out[3][0][1] = 4.0*in[0]; out[3][1][0] = -6.0 + 8.0*in[1]; out[3][1][1] = -7.0 + 8.0*in[0] + 8.0*in[1]; out[4][0][0] = 7.0 - 8.0*in[0] - 8.0*in[1]; out[4][0][1] = 6.0 - 8.0*in[0]; out[4][1][0] = -4.0*in[1]; out[4][1][1] = 5.0 - 4.0*in[0] - 16.0*in[1]; out[5][0][0] = 1.0 - 8.0*in[0] + 4*in[1]; out[5][0][1] = 4.0*in[0]; out[5][1][0] = -4.0*in[1]; out[5][1][1] = -1.0 - 4.0*in[0] + 8.0*in[1]; out[6][0][0] = 16.0 - 32.0*in[0] - 8.0*in[1]; out[6][0][1] = -8.0*in[0]; out[6][1][0] = -16.0*in[1]; out[6][1][1] = 8.0 - 16.0*in[0] - 16.0*in[1]; out[7][0][0] = 8.0 - 16.0*in[0] - 16.0*in[1]; out[7][0][1] = -16.0*in[0]; out[7][1][0] = -8.0*in[1]; out[7][1][1] = 16.0 - 8.0*in[0] - 32.0*in[1]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); switch (direction) { case 0: out[0][0] = sign0*(1.0 - 4.0*in[1]); out[0][1] = 0.0; out[1][0] = sign1*(5.0 - 8.0*in[0]); out[1][1] = sign1*(-4.0*in[1]); out[2][0] = sign2*(-3.0 + 8.0*in[0] + 4.0*in[1]); out[2][1] = sign2*(4.0*in[1]); out[3][0] = -5.0 + 16.0*in[0] + 4.0*in[1]; out[3][1] = -6.0 + 8.0*in[1]; out[4][0] = 7.0 - 8.0*in[0] - 8.0*in[1]; out[4][1] = -4.0*in[1]; out[5][0] = 1.0 - 8.0*in[0] + 4*in[1]; out[5][1] = -4.0*in[1]; out[6][0] = 16.0 - 32.0*in[0] - 8.0*in[1]; out[6][1] = -16.0*in[1]; out[7][0] = 8.0 - 16.0*in[0] - 16.0*in[1]; out[7][1] = -8.0*in[1]; break; case 1: out[2][1] = sign2*(-3.0 + 4.0*in[0] + 8.0*in[1]); out[2][0] = sign2*(4.0*in[0]); out[1][1] = sign1*(1.0 - 4.0*in[0]); out[1][0] = 0.0; out[0][0] = sign0*(-4.0*in[0]); out[0][1] = sign0*(5.0 - 8.0*in[1]); out[3][0] = 4.0*in[0]; out[3][1] = -7.0 + 8.0*in[0] + 8.0*in[1]; out[4][0] = 6.0 - 8.0*in[0]; out[4][1] = 5.0 - 4.0*in[0] - 16.0*in[1]; out[5][0] = 4.0*in[0]; out[5][1] = -1.0 - 4.0*in[0] + 8.0*in[1]; out[6][0] = -8.0*in[0]; out[6][1] = 8.0 - 16.0*in[0] - 16.0*in[1]; out[7][0] = -16.0*in[0]; out[7][1] = 16.0 - 8.0*in[0] - 32.0*in[1]; break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 2; } private: R sign0, sign1, sign2; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALBASIS_HH raviartthomas12dlocalcoefficients.hh000066400000000000000000000022471313314431100365610ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas12d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * @ingroup LocalLayoutImplementation * \brief Layout map for Raviart-Thomas-1 elements on the reference triangle. * * \nosubgrouping */ class RT12DLocalCoefficients { public: //! \brief Standard constructor RT12DLocalCoefficients () : li(8) { for (std::size_t i = 0; i < 3; i++) { li[i] = LocalKey(i,1,0); li[3 + i] = LocalKey(i,1,1); } // last two DOF are associated with the cell (codim = 0) li[6] = LocalKey(0,0,0); li[7] = LocalKey(0,0,1); } //! \brief number of coefficients std::size_t size () const { return 8; } //! \brief get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALCOEFFICIENTS_HH raviartthomas12dlocalinterpolation.hh000066400000000000000000000074451313314431100370140ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas12d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALINTERPOLATION_HH #include #include namespace Dune { /** * @ingroup LocalInterpolationImplementation * \brief First order Raviart-Thomas shape functions on the reference quadrilateral. * * \tparam LB corresponding LocalBasis giving traits * * \nosubgrouping */ template class RT12DLocalInterpolation { public: //! \brief Standard constructor RT12DLocalInterpolation () { sign0 = sign1 = sign2 = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT12DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } n0[0] = 0.0; n0[1] = -1.0; n1[0] = -1.0; n1[1] = 0.0; n2[0] = 1.0/sqrt(2.0); n2[1] = 1.0/sqrt(2.0); c0 = 0.5*n0[0] - 1.0*n0[1]; c1 = -1.0*n1[0] + 0.5*n1[1]; c2 = 0.5*n2[0] + 0.5*n2[1]; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(8); fill(out.begin(), out.end(), 0.0); const int qOrder1 = 4; const Dune::QuadratureRule& rule1 = Dune::QuadratureRules::rule(Dune::GeometryType(Dune::GeometryType::simplex,1), qOrder1); for (typename Dune::QuadratureRule::const_iterator it = rule1.begin(); it != rule1.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0/c0; out[3] += (y[0]*n0[0] + y[1]*n0[1])*(2.0*qPos - 1.0)*it->weight()/c0; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[1] += (y[0]*n1[0] + y[1]*n1[1])*it->weight()*sign1/c1; out[4] += (y[0]*n1[0] + y[1]*n1[1])*(1.0 - 2.0*qPos)*it->weight()/c1; localPos[0] = 1.0 - qPos; localPos[1] = qPos; f.evaluate(localPos, y); out[2] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2/c2; out[5] += (y[0]*n2[0] + y[1]*n2[1])*(2.0*qPos - 1.0)*it->weight()/c2; } const int qOrder2 = 8; const Dune::QuadratureRule& rule2 = Dune::QuadratureRules::rule(Dune::GeometryType(Dune::GeometryType::simplex,2), qOrder2); for (typename Dune::QuadratureRule::const_iterator it = rule2.begin(); it != rule2.end(); ++it) { Dune::FieldVector qPos = it->position(); f.evaluate(qPos, y); out[6] += y[0]*it->weight(); out[7] += y[1]*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0,sign1,sign2; typename LB::Traits::DomainType n0,n1,n2; typename LB::Traits::RangeFieldType c0,c1,c2; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube2d.hh000066400000000000000000000042311313314431100307020ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "raviartthomas1cube2d/raviartthomas1cube2dlocalbasis.hh" #include "raviartthomas1cube2d/raviartthomas1cube2dlocalinterpolation.hh" #include "raviartthomas1cube2d/raviartthomas1cube2dlocalcoefficients.hh" namespace Dune { /** * \brief First order Raviart-Thomas shape functions on quadrilaterals. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT1Cube2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< RT1Cube2DLocalBasis, RT1Cube2DLocalCoefficients, RT1Cube2DLocalInterpolation > > Traits; //! \brief Standard constructor RT1Cube2DLocalFiniteElement () { gt.makeQuadrilateral(); } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT1Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeQuadrilateral(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: RT1Cube2DLocalBasis basis; RT1Cube2DLocalCoefficients coefficients; RT1Cube2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube2d/000077500000000000000000000000001313314431100303615ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube2d/CMakeLists.txt000066400000000000000000000003531313314431100331220ustar00rootroot00000000000000install(FILES raviartthomas1cube2dlocalbasis.hh raviartthomas1cube2dlocalcoefficients.hh raviartthomas1cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas1cube2d) raviartthomas1cube2dlocalbasis.hh000066400000000000000000000140131313314431100367110ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALBASIS_HH #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief First order Raviart-Thomas shape functions on the reference quadrilateral. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class RT1Cube2DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT1Cube2DLocalBasis () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT1Cube2DLocalBasis (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } if (s & 8) { sign3 = -1.0; } } //! \brief number of shape functions unsigned int size () const { return 12; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(12); out[0][0] = sign0*(-1.0 + 4.0*in[0]-3*in[0]*in[0]); out[0][1] = 0.0; out[1][0] = 3.0 - 12.0*in[0] - 6.0*in[1] + 24.0*in[0]*in[1]+9*in[0]*in[0] - 18.0*in[0]*in[0]*in[1]; out[1][1] = 0.0; out[2][0] = sign1*(-2.0*in[0] + 3.0*in[0]*in[0]); out[2][1] = 0.0; out[3][0] = -6.0*in[0] + 12.0*in[0]*in[1] + 9.0*in[0]*in[0] - 18.0*in[0]*in[0]*in[1]; out[3][1] = 0.0; out[4][0] = 0.0; out[4][1] = sign2*(-1.0 + 4.0*in[1] - 3.0*in[1]*in[1]); out[5][0] = 0.0; out[5][1] = -3.0 + 6.0*in[0] + 12.0*in[1] - 24.0*in[0]*in[1] - 9.0*in[1]*in[1] + 18.0*in[0]*in[1]*in[1]; out[6][0] = 0.0; out[6][1] = sign3*(-2.0*in[1] + 3.0*in[1]*in[1]); out[7][0] = 0.0; out[7][1] = 6.0*in[1] - 12.0*in[0]*in[1] - 9.0*in[1]*in[1] + 18.0*in[0]*in[1]*in[1]; out[8][0] = 24.0*in[0] - 36.0*in[0]*in[1] - 24.0*in[0]*in[0] + 36.0*in[0]*in[0]*in[1]; out[8][1] = 0.0; out[9][0] = 0.0; out[9][1] = 24.0*in[1] - 36.0*in[0]*in[1] - 24.0*in[1]*in[1] + 36.0*in[0]*in[1]*in[1]; out[10][0] = -36.0*in[0] + 72.0*in[0]*in[1] + 36.0*in[0]*in[0] - 72.0*in[0]*in[0]*in[1]; out[10][1] = 0.0; out[11][0] = 0.0; out[11][1] = -36.0*in[1] + 72.0*in[0]*in[1] + 36*in[1]*in[1] - 72.0*in[0]*in[1]*in[1]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const typename Traits::DomainType& in, std::vector& out) const { out.resize(12); out[0][0][0] = sign0*(4.0 - 6.0*in[0]); out[0][0][1] = 0.0; out[0][1][0] = 0.0; out[0][1][1] = 0.0; out[1][0][0] = -12.0 + 24.0*in[1] + 18.0*in[0] - 36.0*in[0]*in[1]; out[1][0][1] = -6 + 24.0*in[0] - 18.0*in[0]*in[0]; out[1][1][0] = 0.0; out[1][1][1] = 0.0; out[2][0][0] = sign1*(-2.0 + 6.0*in[0]); out[2][0][1] = 0.0; out[2][1][0] = 0.0; out[2][1][1] = 0.0; out[3][0][0] = -6.0 + 12.0*in[1] + 18.0*in[0] - 36.0*in[0]*in[1]; out[3][0][1] = 12.0*in[0] - 18.0*in[0]*in[0]; out[3][1][0] = 0.0; out[3][1][1] = 0.0; out[4][0][0] = 0.0; out[4][0][1] = 0.0; out[4][1][0] = 0.0; out[4][1][1] = sign2*(4.0 - 6.0*in[1]); out[5][0][0] = 0.0; out[5][0][1] = 0.0; out[5][1][0] = 6.0 - 24.0*in[1] + 18.0*in[1]*in[1]; out[5][1][1] = 12.0 - 24.0*in[0] - 18.0*in[1] + 36.0*in[0]*in[1]; out[6][0][0] = 0.0; out[6][0][1] = 0.0; out[6][1][0] = 0.0; out[6][1][1] = sign3*(-2.0 + 6.0*in[1]); out[7][0][0] = 0.0; out[7][0][1] = 0.0; out[7][1][0] = -12.0*in[1] + 18.0*in[1]*in[1]; out[7][1][1] = 6.0 - 12.0*in[0] - 18.0*in[1] + 36.0*in[1]*in[0]; out[8][0][0] = 24.0 - 36.0*in[1] - 48.0*in[0] + 72.0*in[0]*in[1]; out[8][0][1] = -36.0*in[0] + 36.0*in[0]*in[0]; out[8][1][0] = 0.0; out[8][1][1] = 0.0; out[9][0][0] = 0.0; out[9][0][1] = 0.0; out[9][1][0] = -36.0*in[1] + 36.0*in[1]*in[1]; out[9][1][1] = 24.0 - 36.0*in[0] - 48.0*in[1] + 72.0*in[0]*in[1]; out[10][0][0] = -36.0 + 72.0*in[1] + 72.0*in[0] - 144.0*in[0]*in[1]; out[10][0][1] = 72.0*in[0] - 72.0*in[0]*in[0]; out[10][1][0] = 0.0; out[10][1][1] = 0.0; out[11][0][0] = 0.0; out[11][0][1] = 0.0; out[11][1][0] = 72.0*in[1] - 72.0*in[1]*in[1]; out[11][1][1] = -36.0 + 72.0*in[0] + 72.0*in[1] - 144.0*in[0]*in[1]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 3; } private: R sign0, sign1, sign2, sign3; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALBASIS_HH raviartthomas1cube2dlocalcoefficients.hh000066400000000000000000000023441313314431100402550ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \ingroup LocalLayoutImplementation * \brief Layout map for Raviart-Thomas-1 elements on quadrilaterals * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class RT1Cube2DLocalCoefficients { public: //! \brief Standard constructor RT1Cube2DLocalCoefficients () : li(12) { for (std::size_t i=0; i < 4; i++) { li[2*i] = LocalKey(i,1,0); li[2*i + 1] = LocalKey(i,1,1); } li[8] = LocalKey(0,0,0); li[9] = LocalKey(0,0,1); li[10] = LocalKey(0,0,2); li[11] = LocalKey(0,0,3); } //! number of coefficients std::size_t size () const { return 12; } //! get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALCOEFFICIENTS_HH raviartthomas1cube2dlocalinterpolation.hh000066400000000000000000000077001313314431100405040ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \ingroup LocalInterpolationImplementation * \brief First order Raviart-Thomas shape functions on the reference quadrilateral. * * \tparam LB corresponding LocalBasis giving traits * * \nosubgrouping */ template class RT1Cube2DLocalInterpolation { public: //! \brief Standard constructor RT1Cube2DLocalInterpolation () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT1Cube2DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } if (s & 8) { sign3 = -1.0; } n0[0] = -1.0; n0[1] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n3[0] = 0.0; n3[1] = 1.0; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(12); fill(out.begin(), out.end(), 0.0); const int qOrder = 3; const QuadratureRule& rule1 = QuadratureRules::rule(GeometryType(GeometryType::cube,1), qOrder); for (typename QuadratureRule::const_iterator it = rule1.begin(); it != rule1.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0; out[1] += (y[0]*n0[0] + y[1]*n0[1])*(2.0*qPos - 1.0)*it->weight(); localPos[0] = 1.0; localPos[1] = qPos; f.evaluate(localPos, y); out[2] += (y[0]*n1[0] + y[1]*n1[1])*it->weight()*sign1; out[3] += (y[0]*n1[0] + y[1]*n1[1])*(1.0 - 2.0*qPos)*it->weight(); localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[4] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2; out[5] += (y[0]*n2[0] + y[1]*n2[1])*(1.0 - 2.0*qPos)*it->weight(); localPos[0] = qPos; localPos[1] = 1.0; f.evaluate(localPos, y); out[6] += (y[0]*n3[0] + y[1]*n3[1])*it->weight()*sign3; out[7] += (y[0]*n3[0] + y[1]*n3[1])*(2.0*qPos - 1.0)*it->weight(); } const QuadratureRule& rule2 = QuadratureRules::rule(GeometryType(GeometryType::cube,2), qOrder); for (typename QuadratureRule::const_iterator it=rule2.begin(); it!=rule2.end(); ++it) { FieldVector qPos = it->position(); f.evaluate(qPos, y); out[8] += y[0]*it->weight(); out[9] += y[1]*it->weight(); out[10] += y[0]*qPos[1]*it->weight(); out[11] += y[1]*qPos[0]*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2, sign3; typename LB::Traits::DomainType n0, n1, n2, n3; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube3d.hh000066400000000000000000000042111313314431100307010ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "raviartthomas1cube3d/raviartthomas1cube3dlocalbasis.hh" #include "raviartthomas1cube3d/raviartthomas1cube3dlocalcoefficients.hh" #include "raviartthomas1cube3d/raviartthomas1cube3dlocalinterpolation.hh" namespace Dune { /** * \brief First order Raviart-Thomas shape functions on cubes. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT1Cube3DLocalFiniteElement { public: typedef LocalFiniteElementTraits< RT1Cube3DLocalBasis, RT1Cube3DLocalCoefficients, RT1Cube3DLocalInterpolation > > Traits; //! \brief Standard constructor RT1Cube3DLocalFiniteElement () { gt.makeHexahedron(); } /** * \brief Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ RT1Cube3DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeHexahedron(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: RT1Cube3DLocalBasis basis; RT1Cube3DLocalCoefficients coefficients; RT1Cube3DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube3d/000077500000000000000000000000001313314431100303625ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube3d/CMakeLists.txt000066400000000000000000000003531313314431100331230ustar00rootroot00000000000000install(FILES raviartthomas1cube3dlocalbasis.hh raviartthomas1cube3dlocalcoefficients.hh raviartthomas1cube3dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas1cube3d) raviartthomas1cube3dlocalbasis.hh000066400000000000000000000604731313314431100367260ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube3d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALBASIS_HH #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief First order Raviart-Thomas shape functions on the reference hexahedron. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class RT1Cube3DLocalBasis { public: typedef LocalBasisTraits,R,3,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT1Cube3DLocalBasis () { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; } /** * \brief Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ RT1Cube3DLocalBasis (unsigned int s) { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } if (s & 8) { sign3 = -1.0; } if (s & 16) { sign4 = -1.0; } if (s & 32) { sign5 = -1.0; } } //! \brief number of shape functions unsigned int size () const { return 36; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(36); out[0][0] = sign0*(-3.0*in[0]*in[0] + 4.0*in[0] - 1.0); out[0][1] = 0.0; out[0][2] = 0.0; out[1][0] = sign1*(-2.0*in[0] + 3.0*in[0]*in[0]); out[1][1] = 0.0; out[1][2] = 0.0; out[2][0] = 0.0; out[2][1] = sign2*(-3.0*in[1]*in[1] + 4.0*in[1] - 1.0); out[2][2] = 0.0; out[3][0] = 0.0; out[3][1] = sign3*(3.0*in[1]*in[1] - 2.0*in[1]); out[3][2] = 0.0; out[4][0] = 0.0; out[4][1] = 0.0; out[4][2] = sign4*(-3.0*in[2]*in[2] + 4.0*in[2] - 1.0); out[5][0] = 0.0; out[5][1] = 0.0; out[5][2] = sign5*(3.0*in[2]*in[2] - 2.0*in[2]); out[6][0] = -18.0*in[0]*in[0]*in[1] + 9.0*in[0]*in[0] + 24.0*in[0]*in[1] - 6.0*in[1] -12.0*in[0] + 3.0; out[6][1] = 0.0; out[6][2] = 0.0; out[7][0] = -18.0*in[0]*in[0]*in[1] + 9.0*in[0]*in[0] + 12.0*in[0]*in[1] - 6.0*in[0]; out[7][1] = 0.0; out[7][2] = 0.0; out[8][0] = 0.0; out[8][1] = 18.0*in[0]*in[1]*in[1] - 9.0*in[1]*in[1] - 24.0*in[0]*in[1] + 12.0*in[1] + 6.0*in[0] - 3.0; out[8][2] = 0.0; out[9][0] = 0.0; out[9][1] = 6.0*in[1] - 12.0*in[0]*in[1] - 9.0*in[1]*in[1] + 18.0*in[0]*in[1]*in[1]; out[9][2] = 0.0; out[10][0] = 0.0; out[10][1] = 0.0; out[10][2] = -3.0 + 6.0*in[0] + 12.0*in[2] - 24.0*in[0]*in[2] - 9.0*in[2]*in[2] + 18.0*in[0]*in[2]*in[2]; out[11][0] = 0.0; out[11][1] = 0.0; out[11][2] = 6.0*in[2] - 12.0*in[0]*in[2] - 9.0*in[2]*in[2] + 18.0*in[0]*in[2]*in[2]; out[12][0] = 3.0 - 12.0*in[0] - 6.0*in[2] + 24.0*in[0]*in[2] + 9.0*in[0]*in[0] - 18.0*in[0]*in[0]*in[2]; out[12][1] = 0.0; out[12][2] = 0.0; out[13][0] = -6.0*in[0] + 12.0*in[0]*in[2] + 9.0*in[0]*in[0] - 18.0*in[0]*in[0]*in[2]; out[13][1] = 0.0; out[13][2] = 0.0; out[14][0] = 0.0; out[14][1] = 3.0 - 12.0*in[1] - 6.0*in[2] + 24.0*in[1]*in[2] + 9.0*in[1]*in[1] - 18.0*in[1]*in[1]*in[2]; out[14][2] = 0.0; out[15][0] = 0.0; out[15][1] = -6.0*in[1] + 12.0*in[1]*in[2] + 9.0*in[1]*in[1] - 18.0*in[1]*in[1]*in[2]; out[15][2] = 0.0; out[16][0] = 0.0; out[16][1] = 0.0; out[16][2] = -3.0 + 6.0*in[1] + 12.0*in[2] - 24.0*in[1]*in[2] - 9.0*in[2]*in[2] + 18.0*in[1]*in[2]*in[2]; out[17][0] = 0.0; out[17][1] = 0.0; out[17][2] = 6.0*in[2] - 12.0*in[1]*in[2] - 9.0*in[2]*in[2] + 18.0*in[1]*in[2]*in[2]; out[18][0] = -9.0 + 36.0*in[0] + 18.0*in[1] + 18.0*in[2] - 72.0*in[0]*in[1] - 72.0*in[0]*in[2] - 36.0*in[1]*in[2] + 144.0*in[0]*in[1]*in[2] - 27.0*in[0]*in[0] + 54.0*in[0]*in[0]*in[1] + 54.0*in[0]*in[0]*in[2] - 108.0*in[0]*in[0]*in[1]*in[2]; out[18][1] = 0.0; out[18][2] = 0.0; out[19][0] = 18.0*in[0] - 36.0*in[0]*in[1] - 36.0*in[0]*in[2] + 72.0*in[0]*in[1]*in[2] - 27.0*in[0]*in[0] + 54.0*in[0]*in[0]*in[1] + 54.0*in[0]*in[0]*in[2] - 108.0*in[0]*in[0]*in[1]*in[2]; out[19][1] = 0.0; out[19][2] = 0.0; out[20][0] = 0.0; out[20][1] = 9.0 - 18.0*in[0] - 36.0*in[1] - 18.0*in[2] + 72.0*in[0]*in[1] + 36.0*in[0]*in[2] + 72.0*in[1]*in[2] - 144.0*in[0]*in[1]*in[2] + 27.0*in[1]*in[1] - 54.0*in[1]*in[1]*in[0] - 54.0*in[1]*in[1]*in[2] + 108.0*in[0]*in[1]*in[1]*in[2]; out[20][2] = 0.0; out[21][0] = 0.0; out[21][1] = -18.0*in[1] + 36.0*in[0]*in[1] + 36.0*in[1]*in[2] - 72.0*in[0]*in[1]*in[2] + 27.0*in[1]*in[1] - 54.0*in[0]*in[1]*in[1] - 54.0*in[1]*in[1]*in[2] + 108.0*in[0]*in[1]*in[1]*in[2]; out[21][2] = 0.0; out[22][0] = 0.0; out[22][1] = 0.0; out[22][2] = 9.0 - 18.0*in[0] - 18.0*in[1] - 36.0*in[2] + 36.0*in[0]*in[1] + 72.0*in[0]*in[2] + 72.0*in[1]*in[2] - 144.0*in[0]*in[1]*in[2] + 27.0*in[2]*in[2] - 54.0*in[0]*in[2]*in[2] - 54.0*in[1]*in[2]*in[2] + 108.0*in[0]*in[1]*in[2]*in[2]; out[23][0] = 0.0; out[23][1] = 0.0; out[23][2] = -18.0*in[2] + 36.0*in[0]*in[2] + 36.0*in[1]*in[2] - 72.0*in[0]*in[1]*in[2] + 27.0*in[2]*in[2] - 54.0*in[0]*in[2]*in[2] - 54.0*in[1]*in[2]*in[2] + 108.0*in[0]*in[1]*in[2]*in[2]; out[24][0] = 96.0*in[0] - 144.0*in[0]*in[1] - 144.0*in[0]*in[2] + 216.0*in[0]*in[1]*in[2] - 96.0*in[0]*in[0] + 144.0*in[0]*in[0]*in[1] + 144.0*in[0]*in[0]*in[2] - 216.0*in[0]*in[0]*in[1]*in[2]; out[24][1] = 0.0; out[24][2] = 0.0; out[25][0] = 0.0; out[25][1] = 96.0*in[1] - 144.0*in[0]*in[1] - 144.0*in[1]*in[2] + 216.0*in[0]*in[1]*in[2] - 96.0*in[1]*in[1] + 144.0*in[0]*in[1]*in[1] + 144.0*in[1]*in[1]*in[2] - 216.0*in[0]*in[1]*in[1]*in[2]; out[25][2] = 0.0; out[26][0] = 0.0; out[26][1] = 0.0; out[26][2] = 96.0*in[2] - 144.0*in[0]*in[2] - 144.0*in[1]*in[2] + 216.0*in[0]*in[1]*in[2] - 96.0*in[2]*in[2] + 144.0*in[0]*in[2]*in[2] + 144.0*in[1]*in[2]*in[2] - 216.0*in[0]*in[1]*in[2]*in[2]; out[27][0] = -144.0*in[0] + 288.0*in[0]*in[1] + 216.0*in[0]*in[2] - 432.0*in[0]*in[1]*in[2] + 144.0*in[0]*in[0] - 288.0*in[0]*in[0]*in[1] - 216.0*in[0]*in[0]*in[2] + 432.0*in[0]*in[0]*in[1]*in[2]; out[27][1] = 0.0; out[27][2] = 0.0; out[28][0] = -144.0*in[0] + 216.0*in[0]*in[1] + 288.0*in[0]*in[2] - 432.0*in[0]*in[1]*in[2] + 144.0*in[0]*in[0] - 216.0*in[0]*in[0]*in[1] - 288.0*in[0]*in[0]*in[2] + 432.0*in[0]*in[0]*in[1]*in[2]; out[28][1] = 0.0; out[28][2] = 0.0; out[29][0] = 0.0; out[29][1] = -144.0*in[1] + 288.0*in[0]*in[1] + 216.0*in[1]*in[2] - 432.0*in[0]*in[1]*in[2] + 144.0*in[1]*in[1] - 288.0*in[0]*in[1]*in[1] - 216.0*in[1]*in[1]*in[2] + 432.0*in[0]*in[1]*in[1]*in[2]; out[29][2] = 0.0; out[30][0] = 0.0; out[30][1] = -144.0*in[1] + 216.0*in[0]*in[1] + 288.0*in[1]*in[2] - 432.0*in[0]*in[1]*in[2] + 144.0*in[1]*in[1] - 216.0*in[0]*in[1]*in[1] - 288.0*in[1]*in[1]*in[2] + 432.0*in[0]*in[1]*in[1]*in[2]; out[30][2] = 0.0; out[31][0] = 0.0; out[31][1] = 0.0; out[31][2] =-144.0*in[2] + 288.0*in[0]*in[2] + 216.0*in[1]*in[2] - 432.0*in[0]*in[1]*in[2] + 144.0*in[2]*in[2] - 288.0*in[0]*in[2]*in[2] - 216.0*in[1]*in[2]*in[2] + 432.0*in[0]*in[1]*in[2]*in[2]; out[32][0] = 0.0; out[32][1] = 0.0; out[32][2] = -144.0*in[2] + 216.0*in[0]*in[2] + 288.0*in[1]*in[2] - 432.0*in[0]*in[1]*in[2] + 144.0*in[2]*in[2] - 216.0*in[0]*in[2]*in[2] - 288.0*in[1]*in[2]*in[2] + 432.0*in[0]*in[1]*in[2]*in[2]; out[33][0] = 216.0*in[0] - 432.0*in[0]*in[1] - 432.0*in[0]*in[2] + 864.0*in[0]*in[1]*in[2] - 216.0*in[0]*in[0] + 432.0*in[0]*in[0]*in[1] + 432.0*in[0]*in[0]*in[2] - 864.0*in[0]*in[0]*in[1]*in[2]; out[33][1] = 0.0; out[33][2] = 0.0; out[34][0] = 0.0; out[34][1] = 216.0*in[1] - 432.0*in[0]*in[1] - 432.0*in[1]*in[2] + 864.0*in[0]*in[1]*in[2] - 216.0*in[1]*in[1] + 432.0*in[0]*in[1]*in[1] + 432.0*in[1]*in[1]*in[2] - 864.0*in[0]*in[1]*in[1]*in[2]; out[34][2] = 0.0; out[35][0] = 0.0; out[35][1] = 0.0; out[35][2] = 216.0*in[2] - 432.0*in[0]*in[2] - 432.0*in[1]*in[2] + 864.0*in[0]*in[1]*in[2] - 216.0*in[2]*in[2] + 432.0*in[0]*in[2]*in[2] + 432.0*in[1]*in[2]*in[2] - 864.0*in[0]*in[1]*in[2]*in[2]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const typename Traits::DomainType& in, std::vector& out) const { out.resize(36); out[0][0][0] = sign0*(-6.0*in[0] + 4); out[0][0][1] = 0; out[0][0][2] = 0; out[0][1][0] = 0; out[0][1][1] = 0; out[0][1][2] = 0; out[0][2][0] = 0; out[0][2][1] = 0; out[0][2][2] = 0; out[1][0][0] = sign1*(-2 + 6.0*in[0]); out[1][0][1] = 0; out[1][0][2] = 0; out[1][1][0] = 0; out[1][1][1] = 0; out[1][1][2] = 0; out[1][2][0] = 0; out[1][2][1] = 0; out[1][2][2] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[2][1][0] = 0; out[2][1][1] = sign2*(-6.0*in[1] + 4); out[2][1][2] = 0; out[2][2][0] = 0; out[2][2][1] = 0; out[2][2][2] = 0; out[3][0][0] = 0; out[3][0][1] = 0; out[3][0][2] = 0; out[3][1][0] = 0; out[3][1][1] = sign3*(6.0*in[1] - 2); out[3][1][2] = 0; out[3][2][0] = 0; out[3][2][1] = 0; out[3][2][2] = 0; out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 0; out[4][1][0] = 0; out[4][1][1] = 0; out[4][1][2] = 0; out[4][2][0] = 0; out[4][2][1] = 0; out[4][2][2] = sign4*(-6.0*in[2] + 4); out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[5][1][0] = 0; out[5][1][1] = 0; out[5][1][2] = 0; out[5][2][0] = 0; out[5][2][1] = 0; out[5][2][2] = sign5*(6.0*in[2] - 2); out[6][0][0] = -36.0*in[0]*in[1] + 18.0*in[0] + 24.0*in[1] - 12.0; out[6][0][1] = -18.0*in[0]*in[0] + 24.0*in[0] - 6; out[6][0][2] = 0.0; out[6][1][0] = 0.0; out[6][1][1] = 0.0; out[6][1][2] = 0.0; out[6][2][0] = 0.0; out[6][2][1] = 0.0; out[6][2][2] = 0.0; out[7][0][0] = -36.0*in[0]*in[1] + 18.0*in[0] + 12.0*in[1] - 6.0; out[7][0][1] = -18.0*in[0]*in[0] + 12.0*in[0]; out[7][0][2] = 0.0; out[7][1][0] = 0.0; out[7][1][1] = 0.0; out[7][1][2] = 0.0; out[7][2][0] = 0.0; out[7][2][1] = 0.0; out[7][2][2] = 0.0; out[8][0][0] = 0.0; out[8][0][1] = 0.0; out[8][0][2] = 0.0; out[8][1][0] = 18.0*in[1]*in[1] - 24.0*in[1] + 6.0; out[8][1][1] = 36.0*in[0]*in[1] - 18.0*in[1] - 24.0*in[0] + 12.0; out[8][1][2] = 0.0; out[8][2][0] = 0.0; out[8][2][1] = 0.0; out[8][2][2] = 0.0; out[9][0][0] = 0.0; out[9][0][1] = 0.0; out[9][0][2] = 0.0; out[9][1][0] = -12.0*in[1] + 18.0*in[1]*in[1]; out[9][1][1] = 6.0 - 12.0*in[0] - 18.0*in[1] + 36.0*in[0]*in[1];; out[9][1][2] = 0.0; out[9][2][0] = 0.0; out[9][2][1] = 0.0; out[9][2][2] = 0.0; out[10][0][0] = 0.0; out[10][0][1] = 0.0; out[10][0][2] = 0.0; out[10][1][0] = 0.0; out[10][1][1] = 0.0; out[10][1][2] = 0.0; out[10][2][0] = 6.0 - 24.0*in[2] + 18.0*in[2]*in[2]; out[10][2][1] = 0.0; out[10][2][2] = 12.0 - 24.0*in[0] - 18.0*in[2] + 36.0*in[0]*in[2]; out[11][0][0] = 0.0; out[11][0][1] = 0.0; out[11][0][2] = 0.0; out[11][1][0] = 0.0; out[11][1][1] = 0.0; out[11][1][2] = 0.0; out[11][2][0] = -12.0*in[2] + 18.0*in[2]*in[2]; out[11][2][1] = 0.0; out[11][2][2] = 6.0 - 12.0*in[0] - 18.0*in[2] + 36.0*in[0]*in[2]; out[12][0][0] = -12.0 + 24.0*in[2] + 18.0*in[0] - 36.0*in[0]*in[2]; out[12][0][1] = 0.0; out[12][0][2] = -6.0 + 24.0*in[0] - 18.0*in[0]*in[0]; out[12][1][0] = 0.0; out[12][1][1] = 0.0; out[12][1][2] = 0.0; out[12][2][0] = 0.0; out[12][2][1] = 0.0; out[12][2][2] = 0.0; out[13][0][0] = -6.0 + 12.0*in[2] + 18.0*in[0] - 36.0*in[0]*in[2]; out[13][0][1] = 0.0; out[13][0][2] = 12.0*in[0] - 18.0*in[0]*in[0]; out[13][1][0] = 0.0; out[13][1][1] = 0.0; out[13][1][2] = 0.0; out[13][2][0] = 0.0; out[13][2][1] = 0.0; out[13][2][2] = 0.0; out[14][0][0] = 0.0; out[14][0][1] = 0.0; out[14][0][2] = 0.0; out[14][1][0] = 0.0; out[14][1][1] = -12.0 + 24.0*in[2] + 18.0*in[1] - 36.0*in[1]*in[2]; out[14][1][2] = -6.0 + 24.0*in[1] - 18.0*in[1]*in[1]; out[14][2][0] = 0.0; out[14][2][1] = 0.0; out[14][2][2] = 0.0; out[15][0][0] = 0.0; out[15][0][1] = 0.0; out[15][0][2] = 0.0; out[15][1][0] = 0.0; out[15][1][1] = -6.0 + 12.0*in[2] + 18.0*in[1] - 36.0*in[1]*in[2]; out[15][1][2] = 12.0*in[1] - 18.0*in[1]*in[1]; out[15][2][0] = 0.0; out[15][2][1] = 0.0; out[15][2][2] = 0.0; out[16][0][0] = 0.0; out[16][0][1] = 0.0; out[16][0][2] = 0.0; out[16][1][0] = 0.0; out[16][1][1] = 0.0; out[16][1][2] = 0.0; out[16][2][0] = 0.0; out[16][2][1] = 6.0 - 24.0*in[2] + 18.0*in[2]*in[2]; out[16][2][2] = 12.0 - 24.0*in[1] - 18.0*in[2] + 36.0*in[1]*in[2]; out[17][0][0] = 0.0; out[17][0][1] = 0.0; out[17][0][2] = 0.0; out[17][1][0] = 0.0; out[17][1][1] = 0.0; out[17][1][2] = 0.0; out[17][2][0] = 0.0; out[17][2][1] = -12.0*in[2] + 18.0*in[2]*in[2]; out[17][2][2] = 6.0 - 12.0*in[1] - 18.0*in[2] + 36.0*in[1]*in[2]; out[18][0][0] = 36.0 - 72.0*in[1] - 72.0*in[2] + 144.0*in[1]*in[2] - 54.0*in[0] + 108.0*in[0]*in[1] + 108.0*in[0]*in[2] - 216.0*in[0]*in[1]*in[2]; out[18][0][1] = 18.0 - 72.0*in[0] - 36.0*in[2] + 144.0*in[0]*in[2] + 54.0*in[0]*in[0] - 108.0*in[0]*in[0]*in[2]; out[18][0][2] = 18.0 - 72.0*in[0] - 36.0*in[1] + 144.0*in[0]*in[1] + 54.0*in[0]*in[0] - 108.0*in[0]*in[0]*in[1]; out[18][1][0] = 0.0; out[18][1][1] = 0.0; out[18][1][2] = 0.0; out[18][2][0] = 0.0; out[18][2][1] = 0.0; out[18][2][2] = 0.0; out[19][0][0] = 18 - 36.0*in[1] - 36.0*in[2] + 72.0*in[1]*in[2] - 54.0*in[0] + 108.0*in[0]*in[1] + 108.0*in[0]*in[2] - 216.0*in[0]*in[1]*in[2]; out[19][0][1] = -36.0*in[0] + 72.0*in[0]*in[2] + 54.0*in[0]*in[0] - 108.0*in[0]*in[0]*in[2]; out[19][0][2] = -36.0*in[0] + 72.0*in[0]*in[1] + 54.0*in[0]*in[0] - 108.0*in[0]*in[0]*in[1]; out[19][1][0] = 0.0; out[19][1][1] = 0.0; out[19][1][2] = 0.0; out[19][2][0] = 0.0; out[19][2][1] = 0.0; out[19][2][2] = 0.0; out[20][0][0] = 0.0; out[20][0][1] = 0.0; out[20][0][2] = 0.0; out[20][1][0] = -18.0 + 72.0*in[1] + 36.0*in[2] - 144.0*in[1]*in[2] - 54.0*in[1]*in[1] + 108.0*in[1]*in[1]*in[2]; out[20][1][1] = -36.0 + 72.0*in[0] + 72.0*in[2] - 144.0*in[0]*in[2] + 54.0*in[1] - 108.0*in[1]*in[0] - 108.0*in[1]*in[2] + 216.0*in[0]*in[1]*in[2]; out[20][1][2] = -18.0 + 36.0*in[0] + 72.0*in[1] - 144.0*in[0]*in[1] - 54.0*in[1]*in[1] + 108.0*in[0]*in[1]*in[1]; out[20][2][0] = 0.0; out[20][2][1] = 0.0; out[20][2][2] = 0.0; out[21][0][0] = 0.0; out[21][0][1] = 0.0; out[21][0][2] = 0.0; out[21][1][0] = 36.0*in[1] - 72.0*in[1]*in[2] - 54.0*in[1]*in[1] + 108.0*in[1]*in[1]*in[2]; out[21][1][1] = -18.0 + 36.0*in[0] + 36.0*in[2] - 72.0*in[0]*in[2] + 54.0*in[1] - 108.0*in[0]*in[1] - 108.0*in[1]*in[2] + 216.0*in[0]*in[1]*in[2]; out[21][1][2] = 36.0*in[1] - 72.0*in[0]*in[1] - 54.0*in[1]*in[1] + 108.0*in[0]*in[1]*in[1]; out[21][2][0] = 0.0; out[21][2][1] = 0.0; out[21][2][2] = 0.0; out[22][0][0] = 0.0; out[22][0][1] = 0.0; out[22][0][2] = 0.0; out[22][1][0] = 0.0; out[22][1][1] = 0.0; out[22][1][2] = 0.0; out[22][2][0] = -18.0 + 36.0*in[1] + 72.0*in[2] - 144.0*in[1]*in[2] - 54.0*in[2]*in[2] + 108.0*in[1]*in[2]*in[2]; out[22][2][1] = -18.0 + 36.0*in[0] + 72.0*in[2] - 144.0*in[0]*in[2] - 54.0*in[2]*in[2] + 108.0*in[0]*in[2]*in[2]; out[22][2][2] = -36.0 + 72.0*in[0] + 72.0*in[1] - 144.0*in[0]*in[1] + 54.0*in[2] - 108.0*in[0]*in[2] - 108.0*in[1]*in[2] + 216.0*in[0]*in[1]*in[2]; out[23][0][0] = 0.0; out[23][0][1] = 0.0; out[23][0][2] = 0.0; out[23][1][0] = 0.0; out[23][1][1] = 0.0; out[23][1][2] = 0.0; out[23][2][0] = 36.0*in[2] - 72.0*in[1]*in[2] - 54.0*in[2]*in[2] + 108.0*in[1]*in[2]*in[2]; out[23][2][1] = 36.0*in[2] - 72.0*in[0]*in[2] - 54.0*in[2]*in[2] + 108.0*in[0]*in[2]*in[2]; out[23][2][2] = -18.0 + 36.0*in[0] + 36.0*in[1] - 72.0*in[0]*in[1] + 54.0*in[2] - 108.0*in[0]*in[2] - 108.0*in[1]*in[2] + 216.0*in[0]*in[1]*in[2]; out[24][0][0] = 96.0 - 144.0*in[1] - 144.0*in[2] + 216.0*in[1]*in[2] - 192.0*in[0] + 288.0*in[0]*in[1] + 288.0*in[0]*in[2] - 432.0*in[0]*in[1]*in[2]; out[24][0][1] = -144.0*in[0] + 216.0*in[0]*in[2] + 144.0*in[0]*in[0] - 216.0*in[0]*in[0]*in[2]; out[24][0][2] = -144.0*in[0] + 216.0*in[0]*in[1] + 144.0*in[0]*in[0] - 216.0*in[0]*in[0]*in[1]; out[24][1][0] = 0.0; out[24][1][1] = 0.0; out[24][1][2] = 0.0; out[24][2][0] = 0.0; out[24][2][1] = 0.0; out[24][2][2] = 0.0; out[25][0][0] = 0.0; out[25][0][1] = 0.0; out[25][0][2] = 0.0; out[25][1][0] = -144.0*in[1] + 216.0*in[1]*in[2] + 144.0*in[1]*in[1] - 216.0*in[1]*in[1]*in[2]; out[25][1][1] = 96.0 - 144.0*in[0] - 144.0*in[2] + 216.0*in[0]*in[2] - 192.0*in[1] + 288.0*in[0]*in[1] + 288.0*in[1]*in[2] - 432.0*in[0]*in[1]*in[2]; out[25][1][2] = -144.0*in[1] + 216.0*in[0]*in[1] + 144.0*in[1]*in[1] - 216.0*in[0]*in[1]*in[1]; out[25][2][0] = 0.0; out[25][2][1] = 0.0; out[25][2][2] = 0.0; out[26][0][0] = 0.0; out[26][0][1] = 0.0; out[26][0][2] = 0.0; out[26][1][0] = 0.0; out[26][1][1] = 0.0; out[26][1][2] = 0.0; out[26][2][0] = -144.0*in[2] + 216.0*in[1]*in[2] + 144.0*in[2]*in[2] - 216.0*in[1]*in[2]*in[2]; out[26][2][1] = -144.0*in[2] + 216.0*in[0]*in[2] + 144.0*in[2]*in[2] - 216.0*in[0]*in[2]*in[2]; out[26][2][2] = 96.0 - 144.0*in[0] - 144.0*in[1] + 216.0*in[0]*in[1] - 192.0*in[2] + 288.0*in[0]*in[2] + 288.0*in[1]*in[2] - 432.0*in[0]*in[1]*in[2]; out[27][0][0] = -144.0 + 288.0*in[1] + 216.0*in[2] - 432.0*in[1]*in[2] + 288.0*in[0] - 576.0*in[0]*in[1] - 432.0*in[0]*in[2] + 864.0*in[0]*in[1]*in[2]; out[27][0][1] = 288.0*in[0] - 432.0*in[0]*in[2] - 288.0*in[0]*in[0] + 432.0*in[0]*in[0]*in[2]; out[27][0][2] = 216.0*in[0] - 432.0*in[0]*in[1] - 216.0*in[0]*in[0] + 432.0*in[0]*in[0]*in[1]; out[27][1][0] = 0.0; out[27][1][1] = 0.0; out[27][1][2] = 0.0; out[27][2][0] = 0.0; out[27][2][1] = 0.0; out[27][2][2] = 0.0; out[28][0][0] = -144.0 + 216.0*in[1] + 288.0*in[2] - 432.0*in[1]*in[2] + 288.0*in[0] - 432.0*in[0]*in[1] - 576.0*in[0]*in[2] + 864.0*in[0]*in[1]*in[2]; out[28][0][1] = 216.0*in[0] - 432.0*in[0]*in[2] - 216.0*in[0]*in[0] + 432.0*in[0]*in[0]*in[2]; out[28][0][2] = 288.0*in[0] - 432.0*in[0]*in[1] - 288.0*in[0]*in[0] + 432.0*in[0]*in[0]*in[1]; out[28][1][0] = 0.0; out[28][1][1] = 0.0; out[28][1][2] = 0.0; out[28][2][0] = 0.0; out[28][2][1] = 0.0; out[28][2][2] = 0.0; out[29][0][0] = 0.0; out[29][0][1] = 0.0; out[29][0][2] = 0.0; out[29][1][0] = 288.0*in[1] - 432.0*in[1]*in[2] - 288.0*in[1]*in[1] + 432.0*in[1]*in[1]*in[2]; out[29][1][1] = -144.0 + 288.0*in[0] + 216.0*in[2] - 432.0*in[0]*in[2] + 288.0*in[1] - 576.0*in[0]*in[1] - 432.0*in[1]*in[2] + 864.0*in[0]*in[1]*in[2]; out[29][1][2] = 216.0*in[1] - 432.0*in[0]*in[1] - 216.0*in[1]*in[1] + 432.0*in[0]*in[1]*in[1]; out[29][2][0] = 0.0; out[29][2][1] = 0.0; out[29][2][2] = 0.0; out[30][0][0] = 0.0; out[30][0][1] = 0.0; out[30][0][2] = 0.0; out[30][1][0] = 216.0*in[1] - 432.0*in[1]*in[2] - 216.0*in[1]*in[1] + 432.0*in[1]*in[1]*in[2]; out[30][1][1] = -144.0 + 216.0*in[0] + 288.0*in[2] - 432.0*in[0]*in[2] + 288.0*in[1] - 432.0*in[0]*in[1] - 576.0*in[1]*in[2] + 864.0*in[0]*in[1]*in[2]; out[30][1][2] = 288.0*in[1] - 432.0*in[0]*in[1] - 288.0*in[1]*in[1] + 432.0*in[0]*in[1]*in[1]; out[30][2][0] = 0.0; out[30][2][1] = 0.0; out[30][2][2] = 0.0; out[31][0][0] = 0.0; out[31][0][1] = 0.0; out[31][0][2] = 0.0; out[31][1][0] = 0.0; out[31][1][1] = 0.0; out[31][1][2] = 0.0; out[31][2][0] = 288.0*in[2] - 432.0*in[1]*in[2] - 288.0*in[2]*in[2] + 432.0*in[1]*in[2]*in[2]; out[31][2][1] = 216.0*in[2] - 432.0*in[0]*in[2] - 216.0*in[2]*in[2] + 432.0*in[0]*in[2]*in[2]; out[31][2][2] = -144.0 + 288.0*in[0] + 216.0*in[1] - 432.0*in[0]*in[1] + 288.0*in[2] - 576.0*in[0]*in[2] - 432.0*in[1]*in[2] + 864.0*in[0]*in[1]*in[2]; out[32][0][0] = 0.0; out[32][0][1] = 0.0; out[32][0][2] = 0.0; out[32][1][0] = 0.0; out[32][1][1] = 0.0; out[32][1][2] = 0.0; out[32][2][0] = 216.0*in[2] - 432.0*in[1]*in[2] - 216.0*in[2]*in[2] + 432.0*in[1]*in[2]*in[2]; out[32][2][1] = 288.0*in[2] - 432.0*in[0]*in[2] - 288.0*in[2]*in[2] + 432.0*in[0]*in[2]*in[2]; out[32][2][2] = -144.0 + 216.0*in[0] + 288.0*in[1] - 432.0*in[0]*in[1] + 288.0*in[2] - 432.0*in[0]*in[2] - 576.0*in[1]*in[2] + 864.0*in[0]*in[1]*in[2]; out[33][0][0] = 216.0 - 432.0*in[1] - 432.0*in[2] + 864.0*in[1]*in[2] - 432.0*in[0] + 864.0*in[0]*in[1] + 864.0*in[0]*in[2] - 1728.0*in[0]*in[1]*in[2]; out[33][0][1] = -432.0*in[0] + 864.0*in[0]*in[2] + 432.0*in[0]*in[0] - 864.0*in[0]*in[0]*in[2]; out[33][0][2] = -432.0*in[0] + 864.0*in[0]*in[1] + 432.0*in[0]*in[0] - 864.0*in[0]*in[0]*in[1]; out[33][1][0] = 0.0; out[33][1][1] = 0.0; out[33][1][2] = 0.0; out[33][2][0] = 0.0; out[33][2][1] = 0.0; out[33][2][2] = 0.0; out[34][0][0] = 0.0; out[34][0][1] = 0.0; out[34][0][2] = 0.0; out[34][1][0] = -432.0*in[1] + 864.0*in[1]*in[2] + 432.0*in[1]*in[1] - 864.0*in[1]*in[1]*in[2]; out[34][1][1] = 216.0 - 432.0*in[0] - 432.0*in[2] + 864.0*in[0]*in[2] - 432.0*in[1] + 864.0*in[0]*in[1] + 864.0*in[1]*in[2] - 1728.0*in[0]*in[1]*in[2]; out[34][1][2] = -432.0*in[1] + 864.0*in[0]*in[1] + 432.0*in[1]*in[1] - 864.0*in[0]*in[1]*in[1]; out[34][2][0] = 0.0; out[34][2][1] = 0.0; out[34][2][2] = 0.0; out[35][0][0] = 0.0; out[35][0][1] = 0.0; out[35][0][2] = 0.0; out[35][1][0] = 0.0; out[35][1][1] = 0.0; out[35][1][2] = 0.0; out[35][2][0] = -432.0*in[2] + 864.0*in[1]*in[2] + 432.0*in[2]*in[2] - 864.0*in[1]*in[2]*in[2]; out[35][2][1] = -432.0*in[2] + 864.0*in[0]*in[2] + 432.0*in[2]*in[2] - 864.0*in[0]*in[2]*in[2]; out[35][2][2] = 216.0 - 432.0*in[0] - 432.0*in[1] + 864.0*in[0]*in[1] - 432.0*in[2] + 864.0*in[0]*in[2] + 864.0*in[1]*in[2] - 1728.0*in[0]*in[1]*in[2]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 3; } private: R sign0, sign1, sign2, sign3, sign4, sign5; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALBASIS_HH raviartthomas1cube3dlocalcoefficients.hh000066400000000000000000000024371313314431100402620ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube3d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \ingroup LocalLayoutImplementation * \brief Layout map for Raviart-Thomas-1 elements on quadrilaterals. * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class RT1Cube3DLocalCoefficients { public: //! \brief Standard constructor RT1Cube3DLocalCoefficients () : li(36) { for (std::size_t i = 0; i < 6; i++) { li[i] = LocalKey(i,1,0); li[i + 6] = LocalKey(i,1,1); li[i + 12] = LocalKey(i,1,2); li[i + 18] = LocalKey(i,1,3); } for (std::size_t i = 0; i < 12; i++) { li[i + 24] = LocalKey(0,0,i); } } //! \brief number of coefficients std::size_t size () const { return 36; } //! \brief get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALCOEFFICIENTS_HH raviartthomas1cube3dlocalinterpolation.hh000066400000000000000000000153321313314431100405060ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas1cube3d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \ingroup LocalInterpolationImplementation * \brief First order Raviart-Thomas shape functions on the reference hexahedron. * * \tparam LB corresponding LocalBasis giving traits * * \nosubgrouping */ template class RT1Cube3DLocalInterpolation { public: //! \brief Standard constructor RT1Cube3DLocalInterpolation () { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; } /** * \brief Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ RT1Cube3DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = sign3 = sign4 = sign5 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } if (s & 8) { sign3 = -1.0; } if (s & 16) { sign4 = -1.0; } if (s & 32) { sign5 = -1.0; } n0[0] = -1.0; n0[1] = 0.0; n0[2] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n1[2] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n2[2] = 0.0; n3[0] = 0.0; n3[1] = 1.0; n3[2] = 0.0; n4[0] = 0.0; n4[1] = 0.0; n4[2] = -1.0; n5[0] = 0.0; n5[1] = 0.0; n5[2] = 1.0; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(36); fill(out.begin(), out.end(), 0.0); const int qOrder = 3; const QuadratureRule& rule1 = QuadratureRules::rule(GeometryType(GeometryType::cube,2), qOrder); for (typename QuadratureRule::const_iterator it = rule1.begin(); it != rule1.end(); ++it) { Dune::FieldVector qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = 0.0; localPos[1] = qPos[0]; localPos[2] = qPos[1]; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1] + y[2]*n0[2])*it->weight()*sign0; out[6] += (y[0]*n0[0] + y[1]*n0[1] + y[2]*n0[2])*(2.0*qPos[0] - 1.0)*it->weight(); out[12] += (y[0]*n0[0] + y[1]*n0[1] + y[2]*n0[2])*(2.0*qPos[1] - 1.0)*it->weight(); out[18] += (y[0]*n0[0] + y[1]*n0[1] + y[2]*n0[2])*(2.0*qPos[0] - 1.0)*(2.0*qPos[1] - 1.0)*it->weight(); localPos[0] = 1.0; localPos[1] = qPos[0]; localPos[2] = qPos[1]; f.evaluate(localPos, y); out[1] += (y[0]*n1[0] + y[1]*n1[1] + y[2]*n1[2])*it->weight()*sign1; out[7] += (y[0]*n1[0] + y[1]*n1[1] + y[2]*n1[2])*(1.0 - 2.0*qPos[0])*it->weight(); out[13] += (y[0]*n1[0] + y[1]*n1[1] + y[2]*n1[2])*(1.0 - 2.0*qPos[1])*it->weight(); out[19] += (y[0]*n1[0] + y[1]*n1[1] + y[2]*n1[2])*(1.0 - 2.0*qPos[0])*(2.0*qPos[1] - 1.0)*it->weight(); localPos[0] = qPos[0]; localPos[1] = 0.0; localPos[2] = qPos[1]; f.evaluate(localPos, y); out[2] += (y[0]*n2[0] + y[1]*n2[1] + y[2]*n2[2])*it->weight()*sign2; out[8] += (y[0]*n2[0] + y[1]*n2[1] + y[2]*n2[2])*(1.0 - 2.0*qPos[0])*it->weight(); out[14] += (y[0]*n2[0] + y[1]*n2[1] + y[2]*n2[2])*(2.0*qPos[1] - 1.0)*it->weight(); out[20] += (y[0]*n2[0] + y[1]*n2[1] + y[2]*n2[2])*(1.0 - 2.0*qPos[0])*(2.0*qPos[1] - 1.0)*it->weight(); localPos[0] = qPos[0]; localPos[1] = 1.0; localPos[2] = qPos[1]; f.evaluate(localPos, y); out[3] += (y[0]*n3[0] + y[1]*n3[1] + y[2]*n3[2])*it->weight()*sign3; out[9] += (y[0]*n3[0] + y[1]*n3[1] + y[2]*n3[2])*(2.0*qPos[0] - 1.0)*it->weight(); out[15] += (y[0]*n3[0] + y[1]*n3[1] + y[2]*n3[2])*(1.0 - 2.0*qPos[1])*it->weight(); out[21] += (y[0]*n3[0] + y[1]*n3[1] + y[2]*n3[2])*(2.0*qPos[0] - 1.0)*(2.0*qPos[1] - 1.0)*it->weight(); localPos[0] = qPos[0]; localPos[1] = qPos[1]; localPos[2] = 0.0; f.evaluate(localPos, y); out[4] += (y[0]*n4[0] + y[1]*n4[1] + y[2]*n4[2])*it->weight()*sign4; out[10] += (y[0]*n4[0] + y[1]*n4[1] + y[2]*n4[2])*(1.0 - 2.0*qPos[0])*it->weight(); out[16] += (y[0]*n4[0] + y[1]*n4[1] + y[2]*n4[2])*(1.0 - 2.0*qPos[1])*it->weight(); out[22] += (y[0]*n4[0] + y[1]*n4[1] + y[2]*n4[2])*(1.0 - 2.0*qPos[0])*(2.0*qPos[1] - 1.0)*it->weight(); localPos[0] = qPos[0]; localPos[1] = qPos[1]; localPos[2] = 1.0; f.evaluate(localPos, y); out[5] += (y[0]*n5[0] + y[1]*n5[1] + y[2]*n5[2])*it->weight()*sign5; out[11] += (y[0]*n5[0] + y[1]*n5[1] + y[2]*n5[2])*(2.0*qPos[0] - 1.0)*it->weight(); out[17] += (y[0]*n5[0] + y[1]*n5[1] + y[2]*n5[2])*(2.0*qPos[1] - 1.0)*it->weight(); out[23] += (y[0]*n5[0] + y[1]*n5[1] + y[2]*n5[2])*(2.0*qPos[0] - 1.0)*(2.0*qPos[1] - 1.0)*it->weight(); } const QuadratureRule& rule2 = QuadratureRules::rule(GeometryType(GeometryType::cube,3), qOrder); for (typename QuadratureRule::const_iterator it = rule2.begin(); it != rule2.end(); ++it) { FieldVector qPos = it->position(); f.evaluate(qPos, y); out[24] += y[0]*it->weight(); out[25] += y[1]*it->weight(); out[26] += y[2]*it->weight(); out[27] += y[0]*qPos[1]*it->weight(); out[28] += y[0]*qPos[2]*it->weight(); out[29] += y[1]*qPos[0]*it->weight(); out[30] += y[1]*qPos[2]*it->weight(); out[31] += y[2]*qPos[0]*it->weight(); out[32] += y[2]*qPos[1]*it->weight(); out[33] += y[0]*qPos[1]*qPos[2]*it->weight(); out[34] += y[1]*qPos[0]*qPos[2]*it->weight(); out[35] += y[2]*qPos[0]*qPos[1]*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2, sign3, sign4, sign5; typename LB::Traits::DomainType n0, n1, n2, n3, n4, n5; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas2cube2d.hh000066400000000000000000000042201313314431100307010ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "raviartthomas2cube2d/raviartthomas2cube2dlocalbasis.hh" #include "raviartthomas2cube2d/raviartthomas2cube2dlocalcoefficients.hh" #include "raviartthomas2cube2d/raviartthomas2cube2dlocalinterpolation.hh" namespace Dune { /** * \brief Second order Raviart-Thomas shape functions on cubes. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT2Cube2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< RT2Cube2DLocalBasis, RT2Cube2DLocalCoefficients, RT2Cube2DLocalInterpolation > > Traits; //! \brief Standard constructor RT2Cube2DLocalFiniteElement () { gt.makeQuadrilateral(); } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT2Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeQuadrilateral(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: RT2Cube2DLocalBasis basis; RT2Cube2DLocalCoefficients coefficients; RT2Cube2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas2cube2d/000077500000000000000000000000001313314431100303625ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas2cube2d/CMakeLists.txt000066400000000000000000000003531313314431100331230ustar00rootroot00000000000000install(FILES raviartthomas2cube2dlocalbasis.hh raviartthomas2cube2dlocalcoefficients.hh raviartthomas2cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas2cube2d) raviartthomas2cube2dlocalbasis.hh000066400000000000000000000417031313314431100367210ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas2cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALBASIS_HH #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief Second order Raviart-Thomas shape functions on the reference quadrilateral. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class RT2Cube2DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT2Cube2DLocalBasis () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT2Cube2DLocalBasis (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s & 1) { sign0 = -1.0; } if (s & 2) { sign1 = -1.0; } if (s & 4) { sign2 = -1.0; } if (s & 8) { sign3 = -1.0; } } //! \brief number of shape functions unsigned int size () const { return 24; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(24); out[0][0] = sign0*(-1.0 + 9.0*in[0] - 18.0*in[0]*in[0] + 10.0*in[0]*in[0]*in[0]); out[0][1] = 0.0; out[1][0] = 3.0 - 27.0*in[0] - 6.0*in[1] + 54.0*in[0]*in[1] + 54.0*in[0]*in[0] - 108.0*in[0]*in[0]*in[1] - 30.0*in[0]*in[0]*in[0] + 60.0*in[0]*in[0]*in[0]*in[1]; out[1][1] = 0.0; out[2][0] = sign0*(-5.0 + 45.0*in[0] + 30.0*in[1] - 270.0*in[0]*in[1] - 90.0*in[0]*in[0] - 30.0*in[1]*in[1] + 540.0*in[0]*in[0]*in[1] + 270.0*in[0]*in[1]*in[1] + 50.0*in[0]*in[0]*in[0] - 540.0*in[0]*in[0]*in[1]*in[1] - 300.0*in[0]*in[0]*in[0]*in[1] + 300.0*in[0]*in[0]*in[0]*in[1]*in[1]); out[2][1] = 0.0; out[3][0] = sign1*(3.0*in[0] - 12.0*in[0]*in[0] + 10.0*in[0]*in[0]*in[0]); out[3][1] = 0.0; out[4][0] = 9.0*in[0] - 18.0*in[0]*in[1] - 36.0*in[0]*in[0] + 72.0*in[0]*in[0]*in[1] + 30.0*in[0]*in[0]*in[0] - 60.0*in[0]*in[0]*in[0]*in[1]; out[4][1] = 0.0; out[5][0] = sign1*(15.0*in[0] - 90.0*in[0]*in[1] - 60.0*in[0]*in[0] + 360.0*in[0]*in[0]*in[1] + 90.0*in[0]*in[1]*in[1] + 50.0*in[0]*in[0]*in[0] - 360.0*in[0]*in[0]*in[1]*in[1] - 300.0*in[0]*in[0]*in[0]*in[1] + 300.0*in[0]*in[0]*in[0]*in[1]*in[1]); out[5][1] = 0.0; out[6][0] = 0.0; out[6][1] = sign2*(-1.0 + 9.0*in[1] - 18.0*in[1]*in[1] + 10.0*in[1]*in[1]*in[1]); out[7][0] = 0.0; out[7][1] = -3.0 + 6.0*in[0] + 27.0*in[1] - 54.0*in[0]*in[1] - 54.0*in[1]*in[1] + 108.0*in[0]*in[1]*in[1] + 30.0*in[1]*in[1]*in[1] - 60.0*in[0]*in[1]*in[1]*in[1]; out[8][0] = 0.0; out[8][1] = sign2*(-5.0 + 30.0*in[0] + 45.0*in[1] - 270.0*in[0]*in[1] - 30.0*in[0]*in[0] - 90.0*in[1]*in[1] + 270.0*in[0]*in[0]*in[1] + 540.0*in[0]*in[1]*in[1] + 50.0*in[1]*in[1]*in[1] - 540.0*in[0]*in[0]*in[1]*in[1] - 300.0*in[0]*in[1]*in[1]*in[1] + 300.0*in[1]*in[1]*in[1]*in[0]*in[0]); out[9][0] = 0.0; out[9][1] = sign3*(3.0*in[1] - 12.0*in[1]*in[1] + 10.0*in[1]*in[1]*in[1]); out[10][0] = 0.0; out[10][1] = -9.0*in[1] + 18.0*in[0]*in[1] + 36.0*in[1]*in[1] - 72.0*in[0]*in[1]*in[1] - 30.0*in[1]*in[1]*in[1] + 60.0*in[0]*in[1]*in[1]*in[1]; out[11][0] = 0.0; out[11][1] = sign3*(15.0*in[1] - 90.0*in[0]*in[1] - 60.0*in[1]*in[1] + 90.0*in[0]*in[0]*in[1] + 360.0*in[0]*in[1]*in[1] + 50.0*in[1]*in[1]*in[1] - 360.0*in[0]*in[0]*in[1]*in[1] - 300.0*in[0]*in[1]*in[1]*in[1] + 300.0*in[1]*in[1]*in[1]*in[0]*in[0]); out[12][0] = 324.0*in[0] -1296.0*in[0]*in[1] - 864.0*in[0]*in[0] + 3456.0*in[0]*in[0]*in[1] + 1080.0*in[0]*in[1]*in[1] + 540.0*in[0]*in[0]*in[0] - 2880.0*in[0]*in[0]*in[1]*in[1] - 2160.0*in[0]*in[0]*in[0]*in[1] + 1800.0*in[0]*in[0]*in[0]*in[1]*in[1]; out[12][1] = 0.0; out[13][0] = 0.0; out[13][1] = 324.0*in[1] - 1296.0*in[0]*in[1] - 864.0*in[1]*in[1] + 1080.0*in[0]*in[0]*in[1] + 3456.0*in[0]*in[1]*in[1] + 540.0*in[1]*in[1]*in[1] - 2880.0*in[0]*in[0]*in[1]*in[1] - 2160.0*in[0]*in[1]*in[1]*in[1] + 1800.0*in[1]*in[1]*in[1]*in[0]*in[0]; out[14][0] = -540.0*in[0] + 2160.0*in[0]*in[1] + 1620.0*in[0]*in[0] - 6480.0*in[0]*in[0]*in[1] - 1800.0*in[0]*in[1]*in[1] - 1080.0*in[0]*in[0]*in[0] + 5400.0*in[0]*in[0]*in[1]*in[1] + 4320.0*in[0]*in[0]*in[0]*in[1] - 3600.0*in[0]*in[0]*in[0]*in[1]*in[1]; out[14][1] = 0.0; out[15][0] = 0.0; out[15][1] = -1296.0*in[1] + 6912.0*in[0]*in[1] + 3456.0*in[1]*in[1] - 6480.0*in[0]*in[0]*in[1] - 18432.0*in[0]*in[1]*in[1] - 2160.0*in[1]*in[1]*in[1] + 17280.0*in[0]*in[0]*in[1]*in[1] + 11520.0*in[0]*in[1]*in[1]*in[1] - 10800.0*in[0]*in[0]*in[1]*in[1]*in[1]; out[16][0] = -1296.0*in[0] + 6912.0*in[0]*in[1] + 3456.0*in[0]*in[0] - 6480.0*in[0]*in[1]*in[1] - 18432.0*in[0]*in[0]*in[1] - 2160.0*in[0]*in[0]*in[0] + 17280.0*in[0]*in[0]*in[1]*in[1] + 11520.0*in[1]*in[0]*in[0]*in[0] - 10800.0*in[0]*in[0]*in[0]*in[1]*in[1]; out[16][1] = 0.0; out[17][0] = 0.0; out[17][1] = -540.0*in[1] + 2160.0*in[0]*in[1] + 1620.0*in[1]*in[1] - 1800.0*in[0]*in[0]*in[1] - 6480.0*in[0]*in[1]*in[1] - 1080.0*in[1]*in[1]*in[1] + 5400.0*in[0]*in[0]*in[1]*in[1] + 4320.0*in[0]*in[1]*in[1]*in[1] - 3600.0*in[0]*in[0]*in[1]*in[1]*in[1]; out[18][0] = 2160.0*in[0] - 11520.0*in[0]*in[1] - 6480.0*in[0]*in[0] + 34560.0*in[0]*in[0]*in[1] + 10800.0*in[0]*in[1]*in[1] + 4320.0*in[0]*in[0]*in[0] - 32400.0*in[0]*in[0]*in[1]*in[1] - 23040.0*in[0]*in[0]*in[0]*in[1] + 21600.0*in[0]*in[0]*in[0]*in[1]*in[1]; out[18][1] = 0.0; out[19][0] = 0.0; out[19][1] = 2160.0*in[1] - 11520.0*in[0]*in[1] - 6480.0*in[1]*in[1] + 10800.0*in[0]*in[0]*in[1] + 34560.0*in[0]*in[1]*in[1] + 4320.0*in[1]*in[1]*in[1] - 32400.0*in[0]*in[0]*in[1]*in[1] - 23040.0*in[0]*in[1]*in[1]*in[1] + 21600.0*in[0]*in[0]*in[1]*in[1]*in[1]; out[20][0] = 1080.0*in[0] - 6480.0*in[0]*in[1] - 2880.0*in[0]*in[0] + 17280.0*in[0]*in[0]*in[1] + 6480.0*in[0]*in[1]*in[1] + 1800.0*in[0]*in[0]*in[0] - 17280.0*in[0]*in[0]*in[1]*in[1] - 10800.0*in[0]*in[0]*in[0]*in[1] + 10800.0*in[0]*in[0]*in[0]*in[1]*in[1]; out[20][1] = 0.0; out[21][0] = 0.0; out[21][1] = 1080.0*in[1] - 6480.0*in[0]*in[1] - 2880.0*in[1]*in[1] + 6480.0*in[0]*in[0]*in[1] + 17280.0*in[0]*in[1]*in[1] + 1800.0*in[1]*in[1]*in[1] - 17280.0*in[0]*in[0]*in[1]*in[1] - 10800.0*in[0]*in[1]*in[1]*in[1] + 10800.0*in[0]*in[0]*in[1]*in[1]*in[1]; out[22][0] = -1800.0*in[0] + 10800.0*in[0]*in[1] + 5400.0*in[0]*in[0] - 32400.0*in[0]*in[0]*in[1] - 10800.0*in[0]*in[1]*in[1] - 3600.0*in[0]*in[0]*in[0] + 32400.0*in[0]*in[0]*in[1]*in[1] + 21600.0*in[0]*in[0]*in[0]*in[1] - 21600.0*in[0]*in[0]*in[0]*in[1]*in[1]; out[22][1] = 0.0; out[23][0] = 0.0; out[23][1] = -1800.0*in[1] + 10800.0*in[0]*in[1] + 5400.0*in[1]*in[1] - 10800.0*in[0]*in[0]*in[1] - 32400.0*in[0]*in[1]*in[1] - 3600.0*in[1]*in[1]*in[1] + 32400.0*in[0]*in[0]*in[1]*in[1] + 21600.0*in[0]*in[1]*in[1]*in[1] - 21600.0*in[0]*in[0]*in[1]*in[1]*in[1]; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const typename Traits::DomainType& in, std::vector& out) const { out.resize(24); out[0][0][0] = sign0*(9.0 - 36.0*in[0] + 30.0*in[0]*in[0]); out[0][0][1] = 0.0; out[0][1][0] = 0.0; out[0][1][1] = 0.0; out[1][0][0] = -27.0 + 54.0*in[1] + 108.0*in[0] - 216.0*in[0]*in[1] - 90.0*in[0]*in[0] + 180.0*in[0]*in[0]*in[1]; out[1][0][1] = -6.0 + 54.0*in[0] - 108.0*in[0]*in[0] + 60.0*in[0]*in[0]*in[0]; out[1][1][0] = 0.0; out[1][1][1] = 0.0; out[2][0][0] = sign0*(45.0 - 270.0*in[1] - 180.0*in[0] + 1080.0*in[0]*in[1] + 270.0*in[1]*in[1] + 150.0*in[0]*in[0] - 1080.0*in[0]*in[1]*in[1] - 900.0*in[0]*in[0]*in[1] + 900.0*in[0]*in[0]*in[1]*in[1]); out[2][0][1] = sign0*(30.0 - 270.0*in[0] - 60.0*in[1] + 540.0*in[0]*in[0] + 540.0*in[0]*in[1] - 1080.0*in[0]*in[0]*in[1] - 300.0*in[0]*in[0]*in[0] + 600.0*in[0]*in[0]*in[0]*in[1]); out[2][1][0] = 0.0; out[2][1][1] = 0.0; out[3][0][0] = sign1*(3.0 - 24.0*in[0] + 30.0*in[0]*in[0]); out[3][0][1] = 0.0; out[3][1][0] = 0.0; out[3][1][1] = 0.0; out[4][0][0] = 9.0 - 18.0*in[1] - 72.0*in[0] + 144.0*in[0]*in[1] + 90.0*in[0]*in[0] - 180.0*in[0]*in[0]*in[1]; out[4][0][1] = -18.0*in[0] + 72.0*in[0]*in[0] - 60.0*in[0]*in[0]*in[0]; out[4][1][0] = 0.0; out[4][1][1] = 0.0; out[5][0][0] = sign1*(15.0 - 90.0*in[1] - 120.0*in[0] + 720.0*in[0]*in[1] + 90.0*in[1]*in[1] + 150.0*in[0]*in[0] - 720.0*in[0]*in[1]*in[1] - 900.0*in[0]*in[0]*in[1] + 900.0*in[0]*in[0]*in[1]*in[1]); out[5][0][1] = sign1*(-90.0*in[0] + 360.0*in[0]*in[0] + 180.0*in[0]*in[1] - 720.0*in[0]*in[0]*in[1] - 300.0*in[0]*in[0]*in[0] + 600.0*in[0]*in[0]*in[0]*in[1]); out[5][1][0] = 0.0; out[5][1][1] = 0.0; out[6][0][0] = 0.0; out[6][0][1] = 0.0; out[6][1][0] = 0.0; out[6][1][1] = sign2*(9.0 - 36.0*in[1] + 30.0*in[1]*in[1]); out[7][0][0] = 0.0; out[7][0][1] = 0.0; out[7][1][0] = 6.0 - 54.0*in[1] + 108.0*in[1]*in[1] - 60.0*in[1]*in[1]*in[1]; out[7][1][1] = 27.0 - 54.0*in[0] - 108.0*in[1] + 216.0*in[0]*in[1] + 90.0*in[1]*in[1] - 180.0*in[0]*in[1]*in[1]; out[8][0][0] = 0.0; out[8][0][1] = 0.0; out[8][1][0] = sign2*(30.0 - 270.0*in[1] - 60.0*in[0] + 540.0*in[0]*in[1] + 540.0*in[1]*in[1] - 1080.0*in[0]*in[1]*in[1] - 300.0*in[1]*in[1]*in[1] + 600.0*in[1]*in[1]*in[1]*in[0]); out[8][1][1] = sign2*(45.0 - 270.0*in[0] - 180.0*in[1] + 270.0*in[0]*in[0] + 1080.0*in[0]*in[1] + 150.0*in[1]*in[1] - 1080.0*in[0]*in[0]*in[1] - 900.0*in[0]*in[1]*in[1] + 900.0*in[1]*in[1]*in[0]*in[0]); out[9][0][0] = 0.0; out[9][0][1] = 0.0; out[9][1][0] = 0.0; out[9][1][1] = sign3*(3.0 - 24.0*in[1] + 30.0*in[1]*in[1]); out[10][0][0] = 0.0; out[10][0][1] = 0.0; out[10][1][0] = 18.0*in[1] - 72.0*in[1]*in[1] + 60.0*in[1]*in[1]*in[1]; out[10][1][1] = -9.0 + 18.0*in[0] + 72.0*in[1] - 144.0*in[0]*in[1] - 90.0*in[1]*in[1] + 180.0*in[0]*in[1]*in[1]; out[11][0][0] = 0.0; out[11][0][1] = 0.0; out[11][1][0] = sign3*(-90.0*in[1] + 180.0*in[0]*in[1] + 360.0*in[1]*in[1] - 720.0*in[0]*in[1]*in[1] - 300.0*in[1]*in[1]*in[1] + 600.0*in[1]*in[1]*in[1]*in[0]); out[11][1][1] = sign3*(15.0 - 90.0*in[0] - 120.0*in[1] + 90.0*in[0]*in[0] + 720.0*in[0]*in[1] + 150.0*in[1]*in[1] - 720.0*in[0]*in[0]*in[1] - 900.0*in[0]*in[1]*in[1] + 900.0*in[1]*in[1]*in[0]*in[0]); out[12][0][0] = 324 -1296.0*in[1] - 1728.0*in[0] + 6912.0*in[0]*in[1] + 1080.0*in[1]*in[1] + 1620.0*in[0]*in[0] - 5760.0*in[0]*in[1]*in[1] - 6480.0*in[0]*in[0]*in[1] + 5400.0*in[0]*in[0]*in[1]*in[1]; out[12][0][1] = -1296.0*in[0] + 3456.0*in[0]*in[0] + 2160.0*in[0]*in[1] - 5760.0*in[0]*in[0]*in[1] - 2160.0*in[0]*in[0]*in[0] + 3600.0*in[0]*in[0]*in[0]*in[1]; out[12][1][0] = 0.0; out[12][1][1] = 0.0; out[13][0][0] = 0.0; out[13][0][1] = 0.0; out[13][1][0] = -1296.0*in[1] + 2160.0*in[0]*in[1] + 3456.0*in[1]*in[1] - 5760.0*in[0]*in[1]*in[1] - 2160.0*in[1]*in[1]*in[1] + 3600.0*in[1]*in[1]*in[1]*in[0]; out[13][1][1] = 324.0 - 1296.0*in[0] - 1728.0*in[1] + 1080.0*in[0]*in[0] + 6912.0*in[0]*in[1] + 1620.0*in[1]*in[1] - 5760.0*in[0]*in[0]*in[1] - 6480.0*in[0]*in[1]*in[1] + 5400.0*in[1]*in[1]*in[0]*in[0]; out[14][0][0] = -540.0 + 2160.0*in[1] + 3240.0*in[0] - 12960.0*in[0]*in[1] - 1800.0*in[1]*in[1] - 3240.0*in[0]*in[0] + 10800.0*in[0]*in[1]*in[1] + 12960.0*in[0]*in[0]*in[1] - 10800.0*in[0]*in[0]*in[1]*in[1]; out[14][0][1] = 2160.0*in[0] - 6480.0*in[0]*in[0] - 3600.0*in[0]*in[1] + 10800.0*in[0]*in[0]*in[1] + 4320.0*in[0]*in[0]*in[0] - 7200.0*in[0]*in[0]*in[0]*in[1]; out[14][1][0] = 0.0; out[14][1][1] = 0.0; out[15][0][0] = 0.0; out[15][0][1] = 0.0; out[15][1][0] = 6912.0*in[1] - 12960.0*in[0]*in[1] - 18432.0*in[1]*in[1] + 34560.0*in[0]*in[1]*in[1] + 11520.0*in[1]*in[1]*in[1] - 21600.0*in[0]*in[1]*in[1]*in[1]; out[15][1][1] = -1296.0 + 6912.0*in[0] + 6912.0*in[1] - 6480.0*in[0]*in[0] - 36864.0*in[0]*in[1] - 6480.0*in[1]*in[1] + 34560.0*in[0]*in[0]*in[1] + 34560.0*in[0]*in[1]*in[1] - 32400.0*in[0]*in[0]*in[1]*in[1]; out[16][0][0] = -1296.0 + 6912.0*in[1] + 6912.0*in[0] - 6480.0*in[1]*in[1] - 36864.0*in[0]*in[1] - 6480.0*in[0]*in[0] + 34560.0*in[0]*in[1]*in[1] + 34560.0*in[1]*in[0]*in[0] - 32400.0*in[0]*in[0]*in[1]*in[1]; out[16][0][1] = 6912.0*in[0] - 12960.0*in[0]*in[1] - 18432.0*in[0]*in[0] + 34560.0*in[0]*in[0]*in[1] + 11520.0*in[0]*in[0]*in[0] - 21600.0*in[0]*in[0]*in[0]*in[1]; out[16][1][0] = 0.0; out[16][1][1] = 0.0; out[17][0][0] = 0.0; out[17][0][1] = 0.0; out[17][1][0] = 2160.0*in[1] - 3600.0*in[0]*in[1] - 6480.0*in[1]*in[1] + 10800.0*in[0]*in[1]*in[1] + 4320.0*in[1]*in[1]*in[1] - 7200.0*in[0]*in[1]*in[1]*in[1]; out[17][1][1] = -540.0 + 2160.0*in[0] + 3240.0*in[1] - 1800.0*in[0]*in[0] - 12960.0*in[0]*in[1] - 3240.0*in[1]*in[1] + 10800.0*in[0]*in[0]*in[1] + 12960.0*in[0]*in[1]*in[1] - 10800.0*in[0]*in[0]*in[1]*in[1]; out[18][0][0] = 2160.0 - 11520.0*in[1] - 12960.0*in[0] + 69120.0*in[0]*in[1] + 10800.0*in[1]*in[1] + 12960.0*in[0]*in[0] - 64800.0*in[0]*in[1]*in[1] - 69120.0*in[0]*in[0]*in[1] + 64800.0*in[0]*in[0]*in[1]*in[1]; out[18][0][1] = -11520.0*in[0] + 34560.0*in[0]*in[0] + 21600.0*in[0]*in[1] - 64800.0*in[0]*in[0]*in[1] - 23040.0*in[0]*in[0]*in[0] + 43200.0*in[0]*in[0]*in[0]*in[1]; out[18][1][0] = 0.0; out[18][1][1] = 0.0; out[19][0][0] = 0.0; out[19][0][1] = 0.0; out[19][1][0] = -11520.0*in[1] + 21600.0*in[0]*in[1] + 34560.0*in[1]*in[1] - 64800.0*in[0]*in[1]*in[1] - 23040.0*in[1]*in[1]*in[1] + 43200.0*in[0]*in[1]*in[1]*in[1]; out[19][1][1] = 2160.0 - 11520.0*in[0] - 12960.0*in[1] + 10800.0*in[0]*in[0] + 69120.0*in[0]*in[1] + 12960.0*in[1]*in[1] - 64800.0*in[0]*in[0]*in[1] - 69120.0*in[0]*in[1]*in[1] + 64800.0*in[0]*in[0]*in[1]*in[1]; out[20][0][0] = 1080.0 - 6480.0*in[1] - 5760.0*in[0] + 34560.0*in[0]*in[1] + 6480.0*in[1]*in[1] + 5400.0*in[0]*in[0] - 34560.0*in[0]*in[1]*in[1] - 32400.0*in[0]*in[0]*in[1] + 32400.0*in[0]*in[0]*in[1]*in[1]; out[20][0][1] = -6480.0*in[0] + 17280.0*in[0]*in[0] + 12960.0*in[0]*in[1] - 34560.0*in[0]*in[0]*in[1] - 10800.0*in[0]*in[0]*in[0] + 21600.0*in[0]*in[0]*in[0]*in[1]; out[20][1][0] = 0.0; out[20][1][1] = 0.0; out[21][0][0] = 0.0; out[21][0][1] = 0.0; out[21][1][0] = -6480.0*in[1] + 12960.0*in[0]*in[1] + 17280.0*in[1]*in[1] - 34560.0*in[0]*in[1]*in[1] - 10800.0*in[1]*in[1]*in[1] + 21600.0*in[0]*in[1]*in[1]*in[1]; out[21][1][1] = 1080.0 - 6480.0*in[0] - 5760.0*in[1] + 6480.0*in[0]*in[0] + 34560.0*in[0]*in[1] + 5400.0*in[1]*in[1] - 34560.0*in[0]*in[0]*in[1] - 32400.0*in[0]*in[1]*in[1] + 32400.0*in[0]*in[0]*in[1]*in[1]; out[22][0][0] = -1800.0 + 10800.0*in[1] + 10800.0*in[0] - 64800.0*in[0]*in[1] - 10800.0*in[1]*in[1] - 10800.0*in[0]*in[0] + 64800.0*in[0]*in[1]*in[1] + 64800.0*in[0]*in[0]*in[1] - 64800.0*in[0]*in[0]*in[1]*in[1]; out[22][0][1] = 10800.0*in[0] - 32400.0*in[0]*in[0] - 21600.0*in[0]*in[1] + 64800.0*in[0]*in[0]*in[1] + 21600.0*in[0]*in[0]*in[0] - 43200.0*in[0]*in[0]*in[0]*in[1]; out[22][1][0] = 0.0; out[22][1][1] = 0.0; out[23][0][0] = 0.0; out[23][0][1] = 0.0; out[23][1][0] = 10800.0*in[1] - 21600.0*in[0]*in[1] - 32400.0*in[1]*in[1] + 64800.0*in[0]*in[1]*in[1] + 21600.0*in[1]*in[1]*in[1] - 43200.0*in[0]*in[1]*in[1]*in[1]; out[23][1][1] = -1800.0 + 10800.0*in[0] + 10800.0*in[1] - 10800.0*in[0]*in[0] - 64800.0*in[0]*in[1] - 10800.0*in[1]*in[1] + 64800.0*in[0]*in[0]*in[1] + 64800.0*in[0]*in[1]*in[1] - 64800.0*in[0]*in[0]*in[1]*in[1]; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 5; } private: R sign0, sign1, sign2, sign3; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALBASIS_HH raviartthomas2cube2dlocalcoefficients.hh000066400000000000000000000023671313314431100402640ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas2cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \ingroup LocalLayoutImplementation * \brief Layout map for Raviart-Thomas-2 elements on quadrilaterals * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class RT2Cube2DLocalCoefficients { public: //! \brief Standard constructor RT2Cube2DLocalCoefficients () : li(24) { for (std::size_t i = 0; i < 4; i++) { li[3*i] = LocalKey(i,1,0); li[3*i + 1] = LocalKey(i,1,1); li[3*i + 2] = LocalKey(i,1,2); } for (std::size_t i=0; i<12; i++) { li[12 + i] = LocalKey(0,0,i); } } //! \brief number of coefficients std::size_t size () const { return 24; } //! \brief get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALCOEFFICIENTS_HH raviartthomas2cube2dlocalinterpolation.hh000066400000000000000000000113721313314431100405060ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas2cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \ingroup LocalInterpolationImplementation * \brief Second order Raviart-Thomas shape functions on the reference triangle. * * \tparam LB corresponding LocalBasis giving traits * * \nosubgrouping */ template class RT2Cube2DLocalInterpolation { public: //! \brief Standard constructor RT2Cube2DLocalInterpolation () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT2Cube2DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s & 1) { sign0 *= -1.0; } if (s & 2) { sign1 *= -1.0; } if (s & 4) { sign2 *= -1.0; } if (s & 8) { sign3 *= -1.0; } n0[0] = -1.0; n0[1] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n3[0] = 0.0; n3[1] = 1.0; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(24); fill(out.begin(), out.end(), 0.0); const int qOrder = 6; const QuadratureRule& rule = QuadratureRules::rule(GeometryType(GeometryType::cube,1), qOrder); for (typename QuadratureRule::const_iterator it=rule.begin(); it!=rule.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0; out[1] += (y[0]*n0[0] + y[1]*n0[1])*(2.0*qPos - 1.0)*it->weight(); out[2] += (y[0]*n0[0] + y[1]*n0[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign0; localPos[0] = 1.0; localPos[1] = qPos; f.evaluate(localPos, y); out[3] += (y[0]*n1[0] + y[1]*n1[1])*it->weight()*sign1; out[4] += (y[0]*n1[0] + y[1]*n1[1])*(1.0 - 2.0*qPos)*it->weight(); out[5] += (y[0]*n1[0] + y[1]*n1[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign1; localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[6] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2; out[7] += (y[0]*n2[0] + y[1]*n2[1])*(1.0 - 2.0*qPos)*it->weight(); out[8] += (y[0]*n2[0] + y[1]*n2[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign2; localPos[0] = qPos; localPos[1] = 1.0; f.evaluate(localPos, y); out[9] += (y[0]*n3[0] + y[1]*n3[1])*it->weight()*sign3; out[10] += (y[0]*n3[0] + y[1]*n3[1])*(2.0*qPos - 1.0)*it->weight(); out[11] += (y[0]*n3[0] + y[1]*n3[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign3; } const QuadratureRule& rule2 = QuadratureRules::rule(GeometryType(GeometryType::cube,2), qOrder); for (typename QuadratureRule::const_iterator it = rule2.begin(); it != rule2.end(); ++it) { FieldVector qPos = it->position(); f.evaluate(qPos, y); out[12] += y[0]*it->weight(); out[13] += y[1]*it->weight(); out[14] += y[0]*qPos[0]*it->weight(); out[15] += y[1]*qPos[0]*it->weight(); out[16] += y[0]*qPos[1]*it->weight(); out[17] += y[1]*qPos[1]*it->weight(); out[18] += y[0]*qPos[0]*qPos[1]*it->weight(); out[19] += y[1]*qPos[0]*qPos[1]*it->weight(); out[20] += y[0]*qPos[1]*qPos[1]*it->weight(); out[21] += y[1]*qPos[0]*qPos[0]*it->weight(); out[22] += y[0]*qPos[0]*qPos[1]*qPos[1]*it->weight(); out[23] += y[1]*qPos[0]*qPos[0]*qPos[1]*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2, sign3; typename LB::Traits::DomainType n0, n1, n2, n3; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas3cube2d.hh000066400000000000000000000043011313314431100307020ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "raviartthomas3cube2d/raviartthomas3cube2dlocalbasis.hh" #include "raviartthomas3cube2d/raviartthomas3cube2dlocalcoefficients.hh" #include "raviartthomas3cube2d/raviartthomas3cube2dlocalinterpolation.hh" namespace Dune { /** * \brief Second order Raviart-Thomas shape functions on cubes. * * \note The Jacobian is not implemented. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT3Cube2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< RT3Cube2DLocalBasis, RT3Cube2DLocalCoefficients, RT3Cube2DLocalInterpolation > > Traits; //! \brief Standard constructor RT3Cube2DLocalFiniteElement () { gt.makeQuadrilateral(); } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT3Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeQuadrilateral(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: RT3Cube2DLocalBasis basis; RT3Cube2DLocalCoefficients coefficients; RT3Cube2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas3cube2d/000077500000000000000000000000001313314431100303635ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas3cube2d/CMakeLists.txt000066400000000000000000000003531313314431100331240ustar00rootroot00000000000000install(FILES raviartthomas3cube2dlocalbasis.hh raviartthomas3cube2dlocalcoefficients.hh raviartthomas3cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas3cube2d) raviartthomas3cube2dlocalbasis.hh000066400000000000000000000471311313314431100367240ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas3cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALBASIS_HH #include #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief Second order Raviart-Thomas shape functions on the reference quadrilateral. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class RT3Cube2DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT3Cube2DLocalBasis () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT3Cube2DLocalBasis (std::bitset<4> s) { sign0 = (s[0]) ? -1.0 : 1.0; sign1 = (s[1]) ? -1.0 : 1.0; sign2 = (s[2]) ? -1.0 : 1.0; sign3 = (s[3]) ? -1.0 : 1.0; } //! \brief number of shape functions unsigned int size () const { return 40; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(40); auto const& x = in[0], y = in[1]; const auto tmp1 = - x*(x*(x*(35*x - 80) + 60) - 16) - 1; const auto tmp2 = x*(x*(x*(35*x - 80) + 60) - 16) + 1; const auto tmp3 = 2*y - 1; const auto tmp4 = y*(6*y - 6) + 1; const auto tmp5 = y*(y*(20*y - 30) + 12) - 1; const auto tmp6 = x*(x*(x*(35*x - 60) + 30) - 4); const auto tmp7 = - y*(y*(y*(35*y - 80) + 60) - 16) - 1; const auto tmp8 = y*(y*(y*(35*y - 80) + 60) - 16) + 1; const auto tmp9 = 2*x - 1; const auto tmp10 = x*(6*x - 6) + 1; const auto tmp11 = x*(x*(20*x - 30) + 12) - 1; const auto tmp12 = y*(y*(y*(35*y - 60) + 30) - 4); const auto tmp13 = -x*(x*(x*(7*x - 14) + 9) - 2); const auto tmp14 = x*(x*(x*(7*x - 14) + 9) - 2); const auto tmp15 = x*(x*(2*x - 3) + 1); const auto tmp16 = x*(x*(x*(5*x - 10) + 6) - 1); const auto tmp17 = -y*(y*(y*(7*y - 14) + 9) - 2); const auto tmp18 = y*(y*(2*y - 3) + 1); const auto tmp19 = y*(y*(y*(5*y - 10) + 6) - 1); const auto tmp20 = y*(y*(y*(7*y - 14) + 9) - 2); out[0][0]=sign0*tmp1; out[0][1]=0; out[1][0]=(-3.0*tmp2*tmp3); out[1][1]=0; out[2][0]=sign0*(-5.0*tmp2*tmp4); out[2][1]=0; out[3][0]=(-7.0*tmp2*tmp5); out[3][1]=0; out[4][0]=sign1*tmp6; out[4][1]=0; out[5][0]=(-3.0*tmp6*tmp3); out[5][1]=0; out[6][0]=sign1*(5.0*tmp6*tmp4); out[6][1]=0; out[7][0]=(-7.0*tmp6*tmp5); out[7][1]=0; out[8][0]=0; out[8][1]=sign2*tmp7; out[9][0]=0; out[9][1]=3.0*tmp9*tmp8; out[10][0]=0; out[10][1]=sign2*(-5.0*tmp10*tmp8); out[11][0]=0; out[11][1]=7.0*tmp11*tmp8; out[12][0]=0; out[12][1]=sign3*tmp12; out[13][0]=0; out[13][1]=3.0*tmp9*tmp12; out[14][0]=0; out[14][1]=sign3*5.0*tmp10*tmp12; out[15][0]=0; out[15][1]=7.0*tmp11*tmp12; out[16][0]=10.0*tmp13; out[16][1]=0; out[17][0]=-30.0*tmp14*tmp3; out[17][1]=0; out[18][0]=-50.0*tmp14*tmp4; out[18][1]=0; out[19][0]=-70.0*tmp14*tmp5; out[19][1]=0; out[20][0]=-30.0*tmp15; out[20][1]=0; out[21][0]=-90.0*tmp15*tmp3; out[21][1]=0; out[22][0]=-150.0*tmp15*tmp4; out[22][1]=0; out[23][0]=-210.0*tmp15*tmp5; out[23][1]=0; out[24][0]=-70.0*tmp16; out[24][1]=0; out[25][0]=-210.0*tmp16*tmp3; out[25][1]=0; out[26][0]=-350.0*tmp16*tmp4; out[26][1]=0; out[27][0]=-490.0*tmp16*tmp5; out[27][1]=0; out[28][0]=0; out[28][1]=10.0*tmp17; out[29][0]=0; out[29][1]=-30.0*tmp18; out[30][0]=0; out[30][1]=-70.0*tmp19; out[31][0]=0; out[31][1]=-30.0*tmp9*tmp20; out[32][0]=0; out[32][1]=-90.0*tmp9*tmp18; out[33][0]=0; out[33][1]=-210.0*tmp9*tmp19; out[34][0]=0; out[34][1]=-50.0*tmp10*tmp20; out[35][0]=0; out[35][1]=-150.0*tmp10*tmp18; out[36][0]=0; out[36][1]=-350.0*tmp10*tmp19; out[37][0]=0; out[37][1]=-70.0*tmp11*tmp20; out[38][0]=0; out[38][1]=-210.0*tmp11*tmp18; out[39][0]=0; out[39][1]=-490.0*tmp11*tmp19; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const typename Traits::DomainType& in, std::vector& out) const { out.resize(40); auto const& x = in[0], y = in[1]; const auto tmp2 = x*(x*(x*(35*x - 80) + 60) - 16) + 1; const auto tmp3 = 2*y - 1; const auto tmp4 = y*(6*y - 6) + 1; const auto tmp5 = y*(y*(20*y - 30) + 12) - 1; const auto tmp6 = x*(x*(x*(35*x - 60) + 30) - 4); const auto tmp8 = y*(y*(y*(35*y - 80) + 60) - 16) + 1; const auto tmp9 = 2*x - 1; const auto tmp10 = x*(6*x - 6) + 1; const auto tmp11 = x*(x*(20*x - 30) + 12) - 1; const auto tmp12 = y*(y*(y*(35*y - 60) + 30) - 4); const auto tmp14 = x*(x*(x*(7*x - 14) + 9) - 2); const auto tmp15 = x*(x*(2*x - 3) + 1); const auto tmp16 = x*(x*(x*(5*x - 10) + 6) - 1); const auto tmp18 = y*(y*(2*y - 3) + 1); const auto tmp19 = y*(y*(y*(5*y - 10) + 6) - 1); const auto tmp20 = y*(y*(y*(7*y - 14) + 9) - 2); // temporaries tmp1, tmp7, tmp13, tmp17 are not used in jacobian const auto dxtmp1 = 16 - x*(x*(140*x - 240) + 120); const auto dxtmp2 = x*(x*(140*x - 240) + 120) - 16; const auto dytmp3 = 2; const auto dytmp4 = 12*y - 6; const auto dytmp5 = y*(60*y - 60) + 12; const auto dxtmp6 = x*(x*(140*x - 180) + 60) - 4; const auto dytmp7 = 16 - y*(y*(140*y - 240) + 120); const auto dytmp8 = y*(y*(140*y - 240) + 120) - 16; const auto dxtmp9 = 2; const auto dxtmp10 = 12*x - 6; const auto dxtmp11 = x*(60*x - 60) + 12; const auto dytmp12 = y*(y*(140*y - 180) + 60) - 4; const auto dxtmp13 = 2 - x*(x*(28*x - 42) + 18); const auto dxtmp14 = x*(x*(28*x - 42) + 18) - 2; const auto dxtmp15 = x*(6*x - 6) + 1; const auto dxtmp16 = x*(x*(20*x - 30) + 12) - 1; const auto dytmp17 = 2 - y*(y*(28*y - 42) + 18); const auto dytmp18 = y*(6*y - 6) + 1; const auto dytmp19 = y*(y*(20*y - 30) + 12) - 1; const auto dytmp20 = y*(y*(28*y - 42) + 18) - 2; // x-component out[0][0][0]=sign0*dxtmp1; out[0][1][0]=0; out[1][0][0]=(-3.0*dxtmp2*tmp3); out[1][1][0]=0; out[2][0][0]=sign0*(-5.0*dxtmp2*tmp4); out[2][1][0]=0; out[3][0][0]=(-7.0*dxtmp2*tmp5); out[3][1][0]=0; out[4][0][0]=sign1*dxtmp6; out[4][1][0]=0; out[5][0][0]=(-3.0*dxtmp6*tmp3); out[5][1][0]=0; out[6][0][0]=sign1*(5.0*dxtmp6*tmp4); out[6][1][0]=0; out[7][0][0]=(-7.0*dxtmp6*tmp5); out[7][1][0]=0; out[8][0][0]=0; out[8][1][0]=0; out[9][0][0]=0; out[9][1][0]=3.0*dxtmp9*tmp8; out[10][0][0]=0; out[10][1][0]=sign2*(-5.0*dxtmp10*tmp8); out[11][0][0]=0; out[11][1][0]=7.0*dxtmp11*tmp8; out[12][0][0]=0; out[12][1][0]=0; out[13][0][0]=0; out[13][1][0]=3.0*dxtmp9*tmp12; out[14][0][0]=0; out[14][1][0]=sign3*5.0*dxtmp10*tmp12; out[15][0][0]=0; out[15][1][0]=7.0*dxtmp11*tmp12; out[16][0][0]=10.0*dxtmp13; out[16][1][0]=0; out[17][0][0]=-30.0*dxtmp14*tmp3; out[17][1][0]=0; out[18][0][0]=-50.0*dxtmp14*tmp4; out[18][1][0]=0; out[19][0][0]=-70.0*dxtmp14*tmp5; out[19][1][0]=0; out[20][0][0]=-30.0*dxtmp15; out[20][1][0]=0; out[21][0][0]=-90.0*dxtmp15*tmp3; out[21][1][0]=0; out[22][0][0]=-150.0*dxtmp15*tmp4; out[22][1][0]=0; out[23][0][0]=-210.0*dxtmp15*tmp5; out[23][1][0]=0; out[24][0][0]=-70.0*dxtmp16; out[24][1][0]=0; out[25][0][0]=-210.0*dxtmp16*tmp3; out[25][1][0]=0; out[26][0][0]=-350.0*dxtmp16*tmp4; out[26][1][0]=0; out[27][0][0]=-490.0*dxtmp16*tmp5; out[27][1][0]=0; out[28][0][0]=0; out[28][1][0]=0; out[29][0][0]=0; out[29][1][0]=0; out[30][0][0]=0; out[30][1][0]=0; out[31][0][0]=0; out[31][1][0]=-30.0*dxtmp9*tmp20; out[32][0][0]=0; out[32][1][0]=-90.0*dxtmp9*tmp18; out[33][0][0]=0; out[33][1][0]=-210.0*dxtmp9*tmp19; out[34][0][0]=0; out[34][1][0]=-50.0*dxtmp10*tmp20; out[35][0][0]=0; out[35][1][0]=-150.0*dxtmp10*tmp18; out[36][0][0]=0; out[36][1][0]=-350.0*dxtmp10*tmp19; out[37][0][0]=0; out[37][1][0]=-70.0*dxtmp11*tmp20; out[38][0][0]=0; out[38][1][0]=-210.0*dxtmp11*tmp18; out[39][0][0]=0; out[39][1][0]=-490.0*dxtmp11*tmp19; // y-component out[0][0][1]=0; out[0][1][1]=0; out[1][0][1]=(-3.0*tmp2*dytmp3); out[1][1][1]=0; out[2][0][1]=sign0*(-5.0*tmp2*dytmp4); out[2][1][1]=0; out[3][0][1]=(-7.0*tmp2*dytmp5); out[3][1][1]=0; out[4][0][1]=0; out[4][1][1]=0; out[5][0][1]=(-3.0*tmp6*dytmp3); out[5][1][1]=0; out[6][0][1]=sign1*(5.0*tmp6*dytmp4); out[6][1][1]=0; out[7][0][1]=(-7.0*tmp6*dytmp5); out[7][1][1]=0; out[8][0][1]=0; out[8][1][1]=sign2*dytmp7; out[9][0][1]=0; out[9][1][1]=3.0*tmp9*dytmp8; out[10][0][1]=0; out[10][1][1]=sign2*(-5.0*tmp10*dytmp8); out[11][0][1]=0; out[11][1][1]=7.0*tmp11*dytmp8; out[12][0][1]=0; out[12][1][1]=sign3*dytmp12; out[13][0][1]=0; out[13][1][1]=3.0*tmp9*dytmp12; out[14][0][1]=0; out[14][1][1]=sign3*5.0*tmp10*dytmp12; out[15][0][1]=0; out[15][1][1]=7.0*tmp11*dytmp12; out[16][0][1]=0; out[16][1][1]=0; out[17][0][1]=-30.0*tmp14*dytmp3; out[17][1][1]=0; out[18][0][1]=-50.0*tmp14*dytmp4; out[18][1][1]=0; out[19][0][1]=-70.0*tmp14*dytmp5; out[19][1][1]=0; out[20][0][1]=0; out[20][1][1]=0; out[21][0][1]=-90.0*tmp15*dytmp3; out[21][1][1]=0; out[22][0][1]=-150.0*tmp15*dytmp4; out[22][1][1]=0; out[23][0][1]=-210.0*tmp15*dytmp5; out[23][1][1]=0; out[24][0][1]=0; out[24][1][1]=0; out[25][0][1]=-210.0*tmp16*dytmp3; out[25][1][1]=0; out[26][0][1]=-350.0*tmp16*dytmp4; out[26][1][1]=0; out[27][0][1]=-490.0*tmp16*dytmp5; out[27][1][1]=0; out[28][0][1]=0; out[28][1][1]=10.0*dytmp17; out[29][0][1]=0; out[29][1][1]=-30.0*dytmp18; out[30][0][1]=0; out[30][1][1]=-70.0*dytmp19; out[31][0][1]=0; out[31][1][1]=-30.0*tmp9*dytmp20; out[32][0][1]=0; out[32][1][1]=-90.0*tmp9*dytmp18; out[33][0][1]=0; out[33][1][1]=-210.0*tmp9*dytmp19; out[34][0][1]=0; out[34][1][1]=-50.0*tmp10*dytmp20; out[35][0][1]=0; out[35][1][1]=-150.0*tmp10*dytmp18; out[36][0][1]=0; out[36][1][1]=-350.0*tmp10*dytmp19; out[37][0][1]=0; out[37][1][1]=-70.0*tmp11*dytmp20; out[38][0][1]=0; out[38][1][1]=-210.0*tmp11*dytmp18; out[39][0][1]=0; out[39][1][1]=-490.0*tmp11*dytmp19; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); auto const& x = in[0], y = in[1]; if (direction == 0) { auto tmp3 = 2*y - 1; auto tmp4 = y*(6*y - 6) + 1; auto tmp5 = y*(y*(20*y - 30) + 12) - 1; auto tmp8 = y*(y*(y*(35*y - 80) + 60) - 16) + 1; auto tmp12 = y*(y*(y*(35*y - 60) + 30) - 4); auto tmp18 = y*(y*(2*y - 3) + 1); auto tmp19 = y*(y*(y*(5*y - 10) + 6) - 1); auto tmp20 = y*(y*(y*(7*y - 14) + 9) - 2); auto dxtmp1 = 16 - x*(x*(140*x - 240) + 120); auto dxtmp2 = x*(x*(140*x - 240) + 120) - 16; auto dxtmp6 = x*(x*(140*x - 180) + 60) - 4; auto dxtmp9 = 2; auto dxtmp10 = 12*x - 6; auto dxtmp11 = x*(60*x - 60) + 12; auto dxtmp13 = 2 - x*(x*(28*x - 42) + 18); auto dxtmp14 = x*(x*(28*x - 42) + 18) - 2; auto dxtmp15 = x*(6*x - 6) + 1; auto dxtmp16 = x*(x*(20*x - 30) + 12) - 1; out[0][0]=sign0*dxtmp1; out[0][1]=0; out[1][0]=(-3.0*dxtmp2*tmp3); out[1][1]=0; out[2][0]=sign0*(-5.0*dxtmp2*tmp4); out[2][1]=0; out[3][0]=(-7.0*dxtmp2*tmp5); out[3][1]=0; out[4][0]=sign1*dxtmp6; out[4][1]=0; out[5][0]=(-3.0*dxtmp6*tmp3); out[5][1]=0; out[6][0]=sign1*(5.0*dxtmp6*tmp4); out[6][1]=0; out[7][0]=(-7.0*dxtmp6*tmp5); out[7][1]=0; out[8][0]=0; out[8][1]=0; out[9][0]=0; out[9][1]=3.0*dxtmp9*tmp8; out[10][0]=0; out[10][1]=sign2*(-5.0*dxtmp10*tmp8); out[11][0]=0; out[11][1]=7.0*dxtmp11*tmp8; out[12][0]=0; out[12][1]=0; out[13][0]=0; out[13][1]=3.0*dxtmp9*tmp12; out[14][0]=0; out[14][1]=sign3*5.0*dxtmp10*tmp12; out[15][0]=0; out[15][1]=7.0*dxtmp11*tmp12; out[16][0]=10.0*dxtmp13; out[16][1]=0; out[17][0]=-30.0*dxtmp14*tmp3; out[17][1]=0; out[18][0]=-50.0*dxtmp14*tmp4; out[18][1]=0; out[19][0]=-70.0*dxtmp14*tmp5; out[19][1]=0; out[20][0]=-30.0*dxtmp15; out[20][1]=0; out[21][0]=-90.0*dxtmp15*tmp3; out[21][1]=0; out[22][0]=-150.0*dxtmp15*tmp4; out[22][1]=0; out[23][0]=-210.0*dxtmp15*tmp5; out[23][1]=0; out[24][0]=-70.0*dxtmp16; out[24][1]=0; out[25][0]=-210.0*dxtmp16*tmp3; out[25][1]=0; out[26][0]=-350.0*dxtmp16*tmp4; out[26][1]=0; out[27][0]=-490.0*dxtmp16*tmp5; out[27][1]=0; out[28][0]=0; out[28][1]=0; out[29][0]=0; out[29][1]=0; out[30][0]=0; out[30][1]=0; out[31][0]=0; out[31][1]=-30.0*dxtmp9*tmp20; out[32][0]=0; out[32][1]=-90.0*dxtmp9*tmp18; out[33][0]=0; out[33][1]=-210.0*dxtmp9*tmp19; out[34][0]=0; out[34][1]=-50.0*dxtmp10*tmp20; out[35][0]=0; out[35][1]=-150.0*dxtmp10*tmp18; out[36][0]=0; out[36][1]=-350.0*dxtmp10*tmp19; out[37][0]=0; out[37][1]=-70.0*dxtmp11*tmp20; out[38][0]=0; out[38][1]=-210.0*dxtmp11*tmp18; out[39][0]=0; out[39][1]=-490.0*dxtmp11*tmp19; } else if (direction == 1) { const auto tmp2 = x*(x*(x*(35*x - 80) + 60) - 16) + 1; const auto tmp6 = x*(x*(x*(35*x - 60) + 30) - 4); const auto tmp9 = 2*x - 1; const auto tmp10 = x*(6*x - 6) + 1; const auto tmp11 = x*(x*(20*x - 30) + 12) - 1; const auto tmp14 = x*(x*(x*(7*x - 14) + 9) - 2); const auto tmp15 = x*(x*(2*x - 3) + 1); const auto tmp16 = x*(x*(x*(5*x - 10) + 6) - 1); const auto dytmp3 = 2; const auto dytmp4 = 12*y - 6; const auto dytmp5 = y*(60*y - 60) + 12; const auto dytmp7 = 16 - y*(y*(140*y - 240) + 120); const auto dytmp8 = y*(y*(140*y - 240) + 120) - 16; const auto dytmp12 = y*(y*(140*y - 180) + 60) - 4; const auto dytmp17 = 2 - y*(y*(28*y - 42) + 18); const auto dytmp18 = y*(6*y - 6) + 1; const auto dytmp19 = y*(y*(20*y - 30) + 12) - 1; const auto dytmp20 = y*(y*(28*y - 42) + 18) - 2; out[0][0]=0; out[0][1]=0; out[1][0]=(-3.0*tmp2*dytmp3); out[1][1]=0; out[2][0]=sign0*(-5.0*tmp2*dytmp4); out[2][1]=0; out[3][0]=(-7.0*tmp2*dytmp5); out[3][1]=0; out[4][0]=0; out[4][1]=0; out[5][0]=(-3.0*tmp6*dytmp3); out[5][1]=0; out[6][0]=sign1*(5.0*tmp6*dytmp4); out[6][1]=0; out[7][0]=(-7.0*tmp6*dytmp5); out[7][1]=0; out[8][0]=0; out[8][1]=sign2*dytmp7; out[9][0]=0; out[9][1]=3.0*tmp9*dytmp8; out[10][0]=0; out[10][1]=sign2*(-5.0*tmp10*dytmp8); out[11][0]=0; out[11][1]=7.0*tmp11*dytmp8; out[12][0]=0; out[12][1]=sign3*dytmp12; out[13][0]=0; out[13][1]=3.0*tmp9*dytmp12; out[14][0]=0; out[14][1]=sign3*5.0*tmp10*dytmp12; out[15][0]=0; out[15][1]=7.0*tmp11*dytmp12; out[16][0]=0; out[16][1]=0; out[17][0]=-30.0*tmp14*dytmp3; out[17][1]=0; out[18][0]=-50.0*tmp14*dytmp4; out[18][1]=0; out[19][0]=-70.0*tmp14*dytmp5; out[19][1]=0; out[20][0]=0; out[20][1]=0; out[21][0]=-90.0*tmp15*dytmp3; out[21][1]=0; out[22][0]=-150.0*tmp15*dytmp4; out[22][1]=0; out[23][0]=-210.0*tmp15*dytmp5; out[23][1]=0; out[24][0]=0; out[24][1]=0; out[25][0]=-210.0*tmp16*dytmp3; out[25][1]=0; out[26][0]=-350.0*tmp16*dytmp4; out[26][1]=0; out[27][0]=-490.0*tmp16*dytmp5; out[27][1]=0; out[28][0]=0; out[28][1]=10.0*dytmp17; out[29][0]=0; out[29][1]=-30.0*dytmp18; out[30][0]=0; out[30][1]=-70.0*dytmp19; out[31][0]=0; out[31][1]=-30.0*tmp9*dytmp20; out[32][0]=0; out[32][1]=-90.0*tmp9*dytmp18; out[33][0]=0; out[33][1]=-210.0*tmp9*dytmp19; out[34][0]=0; out[34][1]=-50.0*tmp10*dytmp20; out[35][0]=0; out[35][1]=-150.0*tmp10*dytmp18; out[36][0]=0; out[36][1]=-350.0*tmp10*dytmp19; out[37][0]=0; out[37][1]=-70.0*tmp11*dytmp20; out[38][0]=0; out[38][1]=-210.0*tmp11*dytmp18; out[39][0]=0; out[39][1]=-490.0*tmp11*dytmp19; } else { DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 7; } private: R sign0, sign1, sign2, sign3; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALBASIS_HH raviartthomas3cube2dlocalcoefficients.hh000066400000000000000000000024371313314431100402640ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas3cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \ingroup LocalLayoutImplementation * \brief Layout map for Raviart-Thomas-3 elements on quadrilaterals * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class RT3Cube2DLocalCoefficients { public: //! \brief Standard constructor RT3Cube2DLocalCoefficients () : li(40) { for (std::size_t i = 0; i < 4; i++) { li[4*i] = LocalKey(i,1,0); li[4*i + 1] = LocalKey(i,1,1); li[4*i + 2] = LocalKey(i,1,2); li[4*i + 3] = LocalKey(i,1,3); } for (std::size_t i=0; i<24; i++) { li[16 + i] = LocalKey(0,0,i); } } //! \brief number of coefficients std::size_t size () const { return 40; } //! \brief get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALCOEFFICIENTS_HH raviartthomas3cube2dlocalinterpolation.hh000066400000000000000000000142461313314431100405130ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas3cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \ingroup LocalInterpolationImplementation * \brief Second order Raviart-Thomas shape functions on the reference quadrilateral. * * \tparam LB corresponding LocalBasis giving traits * * \nosubgrouping */ template class RT3Cube2DLocalInterpolation { public: //! \brief Standard constructor RT3Cube2DLocalInterpolation () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT3Cube2DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s & 1) { sign0 *= -1.0; } if (s & 2) { sign1 *= -1.0; } if (s & 4) { sign2 *= -1.0; } if (s & 8) { sign3 *= -1.0; } n0[0] = -1.0; n0[1] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n3[0] = 0.0; n3[1] = 1.0; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(40); fill(out.begin(), out.end(), 0.0); const int qOrder = 9; const QuadratureRule& rule = QuadratureRules::rule(GeometryType(GeometryType::cube,1), qOrder); for (typename QuadratureRule::const_iterator it=rule.begin(); it!=rule.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0; out[1] += (y[0]*n0[0] + y[1]*n0[1])*(2.0*qPos - 1.0)*it->weight(); out[2] += (y[0]*n0[0] + y[1]*n0[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign0; out[3] += (y[0]*n0[0] + y[1]*n0[1])*(20.0*qPos*qPos*qPos - 30.0*qPos*qPos + 12.0*qPos - 1.0)*it->weight(); localPos[0] = 1.0; localPos[1] = qPos; f.evaluate(localPos, y); out[4] += (y[0]*n1[0] + y[1]*n1[1])*it->weight()*sign1; out[5] += (y[0]*n1[0] + y[1]*n1[1])*(1.0 - 2.0*qPos)*it->weight(); out[6] += (y[0]*n1[0] + y[1]*n1[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign1; out[7] += (y[0]*n1[0] + y[1]*n1[1])*(-20.0*qPos*qPos*qPos + 30.0*qPos*qPos - 12.0*qPos + 1.0)*it->weight(); localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[8] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2; out[9] += (y[0]*n2[0] + y[1]*n2[1])*(1.0 - 2.0*qPos)*it->weight(); out[10] += (y[0]*n2[0] + y[1]*n2[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign2; out[11] += (y[0]*n2[0] + y[1]*n2[1])*(-20.0*qPos*qPos*qPos + 30.0*qPos*qPos - 12.0*qPos + 1.0)*it->weight(); localPos[0] = qPos; localPos[1] = 1.0; f.evaluate(localPos, y); out[12] += (y[0]*n3[0] + y[1]*n3[1])*it->weight()*sign3; out[13] += (y[0]*n3[0] + y[1]*n3[1])*(2.0*qPos - 1.0)*it->weight(); out[14] += (y[0]*n3[0] + y[1]*n3[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign3; out[15] += (y[0]*n3[0] + y[1]*n3[1])*(20.0*qPos*qPos*qPos - 30.0*qPos*qPos + 12.0*qPos - 1.0)*it->weight(); } const QuadratureRule& rule2 = QuadratureRules::rule(GeometryType(GeometryType::cube,2), qOrder); for (typename QuadratureRule::const_iterator it = rule2.begin(); it != rule2.end(); ++it) { FieldVector qPos = it->position(); f.evaluate(qPos, y); double l0_x=1.0; double l1_x=2.0*qPos[0]-1.0; double l2_x=6.0*qPos[0]*qPos[0]-6.0*qPos[0]+1.0; double l3_x=20.0*qPos[0]*qPos[0]*qPos[0] - 30.0*qPos[0]*qPos[0] + 12.0*qPos[0] - 1.0; double l0_y=1.0; double l1_y=2.0*qPos[1]-1.0; double l2_y=6.0*qPos[1]*qPos[1]-6.0*qPos[1]+1.0; double l3_y=20.0*qPos[1]*qPos[1]*qPos[1] - 30.0*qPos[1]*qPos[1] + 12.0*qPos[1] - 1.0; out[16] += y[0]*l0_x*l0_y*it->weight(); out[17] += y[0]*l0_x*l1_y*it->weight(); out[18] += y[0]*l0_x*l2_y*it->weight(); out[19] += y[0]*l0_x*l3_y*it->weight(); out[20] += y[0]*l1_x*l0_y*it->weight(); out[21] += y[0]*l1_x*l1_y*it->weight(); out[22] += y[0]*l1_x*l2_y*it->weight(); out[23] += y[0]*l1_x*l3_y*it->weight(); out[24] += y[0]*l2_x*l0_y*it->weight(); out[25] += y[0]*l2_x*l1_y*it->weight(); out[26] += y[0]*l2_x*l2_y*it->weight(); out[27] += y[0]*l2_x*l3_y*it->weight(); out[28] += y[1]*l0_x*l0_y*it->weight(); out[29] += y[1]*l0_x*l1_y*it->weight(); out[30] += y[1]*l0_x*l2_y*it->weight(); out[31] += y[1]*l1_x*l0_y*it->weight(); out[32] += y[1]*l1_x*l1_y*it->weight(); out[33] += y[1]*l1_x*l2_y*it->weight(); out[34] += y[1]*l2_x*l0_y*it->weight(); out[35] += y[1]*l2_x*l1_y*it->weight(); out[36] += y[1]*l2_x*l2_y*it->weight(); out[37] += y[1]*l3_x*l0_y*it->weight(); out[38] += y[1]*l3_x*l1_y*it->weight(); out[39] += y[1]*l3_x*l2_y*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2, sign3; typename LB::Traits::DomainType n0, n1, n2, n3; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas4cube2d.hh000066400000000000000000000043011313314431100307030ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALFINITEELEMENT_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALFINITEELEMENT_HH #include #include "../common/localfiniteelementtraits.hh" #include "raviartthomas4cube2d/raviartthomas4cube2dlocalbasis.hh" #include "raviartthomas4cube2d/raviartthomas4cube2dlocalcoefficients.hh" #include "raviartthomas4cube2d/raviartthomas4cube2dlocalinterpolation.hh" namespace Dune { /** * \brief Second order Raviart-Thomas shape functions on cubes. * * \note The Jacobian is not implemented. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT4Cube2DLocalFiniteElement { public: typedef LocalFiniteElementTraits< RT4Cube2DLocalBasis, RT4Cube2DLocalCoefficients, RT4Cube2DLocalInterpolation > > Traits; //! \brief Standard constructor RT4Cube2DLocalFiniteElement () { gt.makeQuadrilateral(); } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT4Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) { gt.makeQuadrilateral(); } const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } GeometryType type () const { return gt; } private: RT4Cube2DLocalBasis basis; RT4Cube2DLocalCoefficients coefficients; RT4Cube2DLocalInterpolation > interpolation; GeometryType gt; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas4cube2d/000077500000000000000000000000001313314431100303645ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas4cube2d/CMakeLists.txt000066400000000000000000000003531313314431100331250ustar00rootroot00000000000000install(FILES raviartthomas4cube2dlocalbasis.hh raviartthomas4cube2dlocalcoefficients.hh raviartthomas4cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas4cube2d) raviartthomas4cube2dlocalbasis.hh000066400000000000000000000666471313314431100367430ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas4cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALBASIS_HH #include #include #include #include #include "../../common/localbasis.hh" namespace Dune { /** * \ingroup LocalBasisImplementation * \brief Second order Raviart-Thomas shape functions on the reference quadrilateral. * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * * \nosubgrouping */ template class RT4Cube2DLocalBasis { public: typedef LocalBasisTraits,R,2,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Standard constructor RT4Cube2DLocalBasis () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT4Cube2DLocalBasis (std::bitset<4> s) { sign0 = (s[0]) ? -1.0 : 1.0; sign1 = (s[1]) ? -1.0 : 1.0; sign2 = (s[2]) ? -1.0 : 1.0; sign3 = (s[3]) ? -1.0 : 1.0; } //! \brief number of shape functions unsigned int size () const { return 60; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(60); auto const& x = in[0], y = in[1]; const auto l1_x = 2*x - 1; const auto l2_x = x*(6*x - 6) + 1; const auto l3_x = x*(x*(20*x - 30) + 12) - 1; const auto l4_x = x*(x*(x*(70*x - 140) + 90) - 20) + 1; const auto l5_x = x*(x*(x*(x*(252*x - 630) + 560) - 210) + 30) - 1; const auto l1_y = 2*y - 1; const auto l2_y = y*(6*y - 6) + 1; const auto l3_y = y*(y*(20*y - 30) + 12) - 1; const auto l4_y = y*(y*(y*(70*y - 140) + 90) - 20) + 1; const auto l5_y = y*(y*(y*(y*(252*y - 630) + 560) - 210) + 30) - 1; out[0][0]=sign0*(0.5*(-l4_x)+0.5*l5_x); out[0][1]=0.0; out[1][0]=-(1.5)*l4_x*l1_y+1.5*l5_x*l1_y; out[1][1]=0.0; out[2][0]=sign0*(-(2.5)*l4_x*l2_y+2.5*l5_x*l2_y); out[2][1]=0.0; out[3][0]=-(3.5)*l4_x*l3_y+3.5*l5_x*l3_y; out[3][1]=0.0; out[4][0]=sign0*(-(4.5)*l4_x*l4_y+4.5*l5_x*l4_y); out[4][1]=0.0; out[5][0]=sign1*(0.5*l4_x+0.5*l5_x); out[5][1]=0.0; out[6][0]=-(1.5)*l4_x*l1_y-1.5*l5_x*l1_y; out[6][1]=0.0; out[7][0]=sign1*(2.5*l4_x*l2_y+2.5*l5_x*l2_y); out[7][1]=0.0; out[8][0]=-(3.5)*l4_x*l3_y-3.5*l5_x*l3_y; out[8][1]=0.0; out[9][0]=sign1*(4.5*l4_x*l4_y+4.5*l5_x*l4_y); out[9][1]=0.0; out[10][0]=0.0; out[10][1]=sign2*(0.5*(-l4_y)+0.5*l5_y); out[11][0]=0.0; out[11][1]=1.5*l1_x*l4_y-1.5*l1_x*l5_y; out[12][0]=0.0; out[12][1]=sign2*(-(2.5)*l2_x*l4_y+2.5*l2_x*l5_y); out[13][0]=0.0; out[13][1]=3.5*l3_x*l4_y-3.5*l3_x*l5_y; out[14][0]=0.0; out[14][1]=sign2*(-(4.5)*l4_x*l4_y+4.5*l4_x*l5_y); out[15][0]=0.0; out[15][1]=sign3*(0.5*l4_y+0.5*l5_y); out[16][0]=0.0; out[16][1]=1.5*l1_x*l4_y+1.5*l1_x*l5_y; out[17][0]=0.0; out[17][1]=sign3*(2.5*l2_x*l4_y+2.5*l2_x*l5_y); out[18][0]=0.0; out[18][1]=3.5*l3_x*l4_y+3.5*l3_x*l5_y; out[19][0]=0.0; out[19][1]=sign3*(4.5*l4_x*l4_y+4.5*l4_x*l5_y); out[20][0]=1.0-l4_x; out[20][1]=0.0; out[21][0]=3.0*l1_y-3.0*l4_x*l1_y; out[21][1]=0.0; out[22][0]=5.0*l2_y-5.0*l4_x*l2_y; out[22][1]=0.0; out[23][0]=7.0*l3_y-7.0*l4_x*l3_y; out[23][1]=0.0; out[24][0]=9.0*l4_y-9.0*l4_x*l4_y; out[24][1]=0.0; out[25][0]=3.0*l1_x-3.0*l5_x; out[25][1]=0.0; out[26][0]=9.0*l1_x*l1_y-9.0*l5_x*l1_y; out[26][1]=0.0; out[27][0]=15.0*l1_x*l2_y-15.0*l5_x*l2_y; out[27][1]=0.0; out[28][0]=21.0*l1_x*l3_y-21.0*l5_x*l3_y; out[28][1]=0.0; out[29][0]=27.0*l1_x*l4_y-27.0*l5_x*l4_y; out[29][1]=0.0; out[30][0]=5.0*l2_x-5.0*l4_x; out[30][1]=0.0; out[31][0]=15.0*l2_x*l1_y-15.0*l4_x*l1_y; out[31][1]=0.0; out[32][0]=25.0*l2_x*l2_y-25.0*l4_x*l2_y; out[32][1]=0.0; out[33][0]=35.0*l2_x*l3_y-35.0*l4_x*l3_y; out[33][1]=0.0; out[34][0]=45.0*l2_x*l4_y-45.0*l4_x*l4_y; out[34][1]=0.0; out[35][0]=7.0*l3_x-7.0*l5_x; out[35][1]=0.0; out[36][0]=21.0*l3_x*l1_y-21.0*l5_x*l1_y; out[36][1]=0.0; out[37][0]=35.0*l3_x*l2_y-35.0*l5_x*l2_y; out[37][1]=0.0; out[38][0]=49.0*l3_x*l3_y-49.0*l5_x*l3_y; out[38][1]=0.0; out[39][0]=63.0*l3_x*l4_y-63.0*l5_x*l4_y; out[39][1]=0.0; out[40][0]=0.0; out[40][1]=1.0-l4_y; out[41][0]=0.0; out[41][1]=3.0*l1_y-3.0*l5_y; out[42][0]=0.0; out[42][1]=5.0*l2_y-5.0*l4_y; out[43][0]=0.0; out[43][1]=7.0*l3_y-7.0*l5_y; out[44][0]=0.0; out[44][1]=3.0*l1_x-3.0*l1_x*l4_y; out[45][0]=0.0; out[45][1]=9.0*l1_x*l1_y-9.0*l1_x*l5_y; out[46][0]=0.0; out[46][1]=15.0*l1_x*l2_y-15.0*l1_x*l4_y; out[47][0]=0.0; out[47][1]=21.0*l1_x*l3_y-21.0*l1_x*l5_y; out[48][0]=0.0; out[48][1]=5.0*l2_x-5.0*l2_x*l4_y; out[49][0]=0.0; out[49][1]=15.0*l2_x*l1_y-15.0*l2_x*l5_y; out[50][0]=0.0; out[50][1]=25.0*l2_x*l2_y-25.0*l2_x*l4_y; out[51][0]=0.0; out[51][1]=35.0*l2_x*l3_y-35.0*l2_x*l5_y; out[52][0]=0.0; out[52][1]=7.0*l3_x-7.0*l3_x*l4_y; out[53][0]=0.0; out[53][1]=21.0*l3_x*l1_y-21.0*l3_x*l5_y; out[54][0]=0.0; out[54][1]=35.0*l3_x*l2_y-35.0*l3_x*l4_y; out[55][0]=0.0; out[55][1]=49.0*l3_x*l3_y-49.0*l3_x*l5_y; out[56][0]=0.0; out[56][1]=9.0*l4_x-9.0*l4_x*l4_y; out[57][0]=0.0; out[57][1]=27.0*l4_x*l1_y-27.0*l4_x*l5_y; out[58][0]=0.0; out[58][1]=45.0*l4_x*l2_y-45.0*l4_x*l4_y; out[59][0]=0.0; out[59][1]=63.0*l4_x*l3_y-63.0*l4_x*l5_y; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const typename Traits::DomainType& in, std::vector& out) const { out.resize(60); auto const& x = in[0], y = in[1]; const auto l1_x = 2*x - 1; const auto l2_x = x*(6*x - 6) + 1; const auto l3_x = x*(x*(20*x - 30) + 12) - 1; const auto l4_x = x*(x*(x*(70*x - 140) + 90) - 20) + 1; const auto l5_x = x*(x*(x*(x*(252*x - 630) + 560) - 210) + 30) - 1; const auto l1_y = 2*y - 1; const auto l2_y = y*(6*y - 6) + 1; const auto l3_y = y*(y*(20*y - 30) + 12) - 1; const auto l4_y = y*(y*(y*(70*y - 140) + 90) - 20) + 1; const auto l5_y = y*(y*(y*(y*(252*y - 630) + 560) - 210) + 30) - 1; const auto dxl1_x = 2.0; const auto dxl2_x = 12*x - 6; const auto dxl3_x = x*(60*x - 60) + 12; const auto dxl4_x = x*(x*(280*x - 420) + 180) - 20; const auto dxl5_x = x*(x*(x*(1260*x - 2520) + 1680) - 420) + 30; const auto dyl1_y = 2.0; const auto dyl2_y = 12*y - 6; const auto dyl3_y = y*(60*y - 60) + 12; const auto dyl4_y = y*(y*(280*y - 420) + 180) - 20; const auto dyl5_y = y*(y*(y*(1260*y - 2520) + 1680) - 420) + 30; // x-component out[0][0][0]=sign0*(0.5*(-dxl4_x)+0.5*dxl5_x); out[0][1][0]=0.0; out[1][0][0]=-(1.5)*dxl4_x*l1_y+1.5*dxl5_x*l1_y; out[1][1][0]=0.0; out[2][0][0]=sign0*(-(2.5)*dxl4_x*l2_y+2.5*dxl5_x*l2_y); out[2][1][0]=0.0; out[3][0][0]=-(3.5)*dxl4_x*l3_y+3.5*dxl5_x*l3_y; out[3][1][0]=0.0; out[4][0][0]=sign0*(-(4.5)*dxl4_x*l4_y+4.5*dxl5_x*l4_y); out[4][1][0]=0.0; out[5][0][0]=sign1*(0.5*dxl4_x+0.5*dxl5_x); out[5][1][0]=0.0; out[6][0][0]=-(1.5)*dxl4_x*l1_y-1.5*dxl5_x*l1_y; out[6][1][0]=0.0; out[7][0][0]=sign1*(2.5*dxl4_x*l2_y+2.5*dxl5_x*l2_y); out[7][1][0]=0.0; out[8][0][0]=-(3.5)*dxl4_x*l3_y-3.5*dxl5_x*l3_y; out[8][1][0]=0.0; out[9][0][0]=sign1*(4.5*dxl4_x*l4_y+4.5*dxl5_x*l4_y); out[9][1][0]=0.0; out[10][0][0]=0.0; out[10][1][0]=0.0; out[11][0][0]=0.0; out[11][1][0]=1.5*dxl1_x*l4_y-1.5*dxl1_x*l5_y; out[12][0][0]=0.0; out[12][1][0]=sign2*(-(2.5)*dxl2_x*l4_y+2.5*dxl2_x*l5_y); out[13][0][0]=0.0; out[13][1][0]=3.5*dxl3_x*l4_y-3.5*dxl3_x*l5_y; out[14][0][0]=0.0; out[14][1][0]=sign2*(-(4.5)*dxl4_x*l4_y+4.5*dxl4_x*l5_y); out[15][0][0]=0.0; out[15][1][0]=0.0; out[16][0][0]=0.0; out[16][1][0]=1.5*dxl1_x*l4_y+1.5*dxl1_x*l5_y; out[17][0][0]=0.0; out[17][1][0]=sign3*(2.5*dxl2_x*l4_y+2.5*dxl2_x*l5_y); out[18][0][0]=0.0; out[18][1][0]=3.5*dxl3_x*l4_y+3.5*dxl3_x*l5_y; out[19][0][0]=0.0; out[19][1][0]=sign3*(4.5*dxl4_x*l4_y+4.5*dxl4_x*l5_y); out[20][0][0]=-dxl4_x; out[20][1][0]=0.0; out[21][0][0]=-3.0*dxl4_x*l1_y; out[21][1][0]=0.0; out[22][0][0]=-5.0*dxl4_x*l2_y; out[22][1][0]=0.0; out[23][0][0]=-7.0*dxl4_x*l3_y; out[23][1][0]=0.0; out[24][0][0]=-9.0*dxl4_x*l4_y; out[24][1][0]=0.0; out[25][0][0]=3.0*dxl1_x-3.0*dxl5_x; out[25][1][0]=0.0; out[26][0][0]=9.0*dxl1_x*l1_y-9.0*dxl5_x*l1_y; out[26][1][0]=0.0; out[27][0][0]=15.0*dxl1_x*l2_y-15.0*dxl5_x*l2_y; out[27][1][0]=0.0; out[28][0][0]=21.0*dxl1_x*l3_y-21.0*dxl5_x*l3_y; out[28][1][0]=0.0; out[29][0][0]=27.0*dxl1_x*l4_y-27.0*dxl5_x*l4_y; out[29][1][0]=0.0; out[30][0][0]=5.0*dxl2_x-5.0*dxl4_x; out[30][1][0]=0.0; out[31][0][0]=15.0*dxl2_x*l1_y-15.0*dxl4_x*l1_y; out[31][1][0]=0.0; out[32][0][0]=25.0*dxl2_x*l2_y-25.0*dxl4_x*l2_y; out[32][1][0]=0.0; out[33][0][0]=35.0*dxl2_x*l3_y-35.0*dxl4_x*l3_y; out[33][1][0]=0.0; out[34][0][0]=45.0*dxl2_x*l4_y-45.0*dxl4_x*l4_y; out[34][1][0]=0.0; out[35][0][0]=7.0*dxl3_x-7.0*dxl5_x; out[35][1][0]=0.0; out[36][0][0]=21.0*dxl3_x*l1_y-21.0*dxl5_x*l1_y; out[36][1][0]=0.0; out[37][0][0]=35.0*dxl3_x*l2_y-35.0*dxl5_x*l2_y; out[37][1][0]=0.0; out[38][0][0]=49.0*dxl3_x*l3_y-49.0*dxl5_x*l3_y; out[38][1][0]=0.0; out[39][0][0]=63.0*dxl3_x*l4_y-63.0*dxl5_x*l4_y; out[39][1][0]=0.0; out[40][0][0]=0.0; out[40][1][0]=0.0; out[41][0][0]=0.0; out[41][1][0]=0.0; out[42][0][0]=0.0; out[42][1][0]=0.0; out[43][0][0]=0.0; out[43][1][0]=0.0; out[44][0][0]=0.0; out[44][1][0]=3.0*dxl1_x-3.0*dxl1_x*l4_y; out[45][0][0]=0.0; out[45][1][0]=9.0*dxl1_x*l1_y-9.0*dxl1_x*l5_y; out[46][0][0]=0.0; out[46][1][0]=15.0*dxl1_x*l2_y-15.0*dxl1_x*l4_y; out[47][0][0]=0.0; out[47][1][0]=21.0*dxl1_x*l3_y-21.0*dxl1_x*l5_y; out[48][0][0]=0.0; out[48][1][0]=5.0*dxl2_x-5.0*dxl2_x*l4_y; out[49][0][0]=0.0; out[49][1][0]=15.0*dxl2_x*l1_y-15.0*dxl2_x*l5_y; out[50][0][0]=0.0; out[50][1][0]=25.0*dxl2_x*l2_y-25.0*dxl2_x*l4_y; out[51][0][0]=0.0; out[51][1][0]=35.0*dxl2_x*l3_y-35.0*dxl2_x*l5_y; out[52][0][0]=0.0; out[52][1][0]=7.0*dxl3_x-7.0*dxl3_x*l4_y; out[53][0][0]=0.0; out[53][1][0]=21.0*dxl3_x*l1_y-21.0*dxl3_x*l5_y; out[54][0][0]=0.0; out[54][1][0]=35.0*dxl3_x*l2_y-35.0*dxl3_x*l4_y; out[55][0][0]=0.0; out[55][1][0]=49.0*dxl3_x*l3_y-49.0*dxl3_x*l5_y; out[56][0][0]=0.0; out[56][1][0]=9.0*dxl4_x-9.0*dxl4_x*l4_y; out[57][0][0]=0.0; out[57][1][0]=27.0*dxl4_x*l1_y-27.0*dxl4_x*l5_y; out[58][0][0]=0.0; out[58][1][0]=45.0*dxl4_x*l2_y-45.0*dxl4_x*l4_y; out[59][0][0]=0.0; out[59][1][0]=63.0*dxl4_x*l3_y-63.0*dxl4_x*l5_y; // y-component out[0][0][1]=0.0; out[0][1][1]=0.0; out[1][0][1]=-(1.5)*l4_x*dyl1_y+1.5*l5_x*dyl1_y; out[1][1][1]=0.0; out[2][0][1]=sign0*(-(2.5)*l4_x*dyl2_y+2.5*l5_x*dyl2_y); out[2][1][1]=0.0; out[3][0][1]=-(3.5)*l4_x*dyl3_y+3.5*l5_x*dyl3_y; out[3][1][1]=0.0; out[4][0][1]=sign0*(-(4.5)*l4_x*dyl4_y+4.5*l5_x*dyl4_y); out[4][1][1]=0.0; out[5][0][1]=0.0; out[5][1][1]=0.0; out[6][0][1]=-(1.5)*l4_x*dyl1_y-1.5*l5_x*dyl1_y; out[6][1][1]=0.0; out[7][0][1]=sign1*(2.5*l4_x*dyl2_y+2.5*l5_x*dyl2_y); out[7][1][1]=0.0; out[8][0][1]=-(3.5)*l4_x*dyl3_y-3.5*l5_x*dyl3_y; out[8][1][1]=0.0; out[9][0][1]=sign1*(4.5*l4_x*dyl4_y+4.5*l5_x*dyl4_y); out[9][1][1]=0.0; out[10][0][1]=0.0; out[10][1][1]=sign2*(0.5*(-dyl4_y)+0.5*dyl5_y); out[11][0][1]=0.0; out[11][1][1]=1.5*l1_x*dyl4_y-1.5*l1_x*dyl5_y; out[12][0][1]=0.0; out[12][1][1]=sign2*(-(2.5)*l2_x*dyl4_y+2.5*l2_x*dyl5_y); out[13][0][1]=0.0; out[13][1][1]=3.5*l3_x*dyl4_y-3.5*l3_x*dyl5_y; out[14][0][1]=0.0; out[14][1][1]=sign2*(-(4.5)*l4_x*dyl4_y+4.5*l4_x*dyl5_y); out[15][0][1]=0.0; out[15][1][1]=sign3*(0.5*dyl4_y+0.5*dyl5_y); out[16][0][1]=0.0; out[16][1][1]=1.5*l1_x*dyl4_y+1.5*l1_x*dyl5_y; out[17][0][1]=0.0; out[17][1][1]=sign3*(2.5*l2_x*dyl4_y+2.5*l2_x*dyl5_y); out[18][0][1]=0.0; out[18][1][1]=3.5*l3_x*dyl4_y+3.5*l3_x*dyl5_y; out[19][0][1]=0.0; out[19][1][1]=sign3*(4.5*l4_x*dyl4_y+4.5*l4_x*dyl5_y); out[20][0][1]=0.0; out[20][1][1]=0.0; out[21][0][1]=3.0*dyl1_y-3.0*l4_x*dyl1_y; out[21][1][1]=0.0; out[22][0][1]=5.0*dyl2_y-5.0*l4_x*dyl2_y; out[22][1][1]=0.0; out[23][0][1]=7.0*dyl3_y-7.0*l4_x*dyl3_y; out[23][1][1]=0.0; out[24][0][1]=9.0*dyl4_y-9.0*l4_x*dyl4_y; out[24][1][1]=0.0; out[25][0][1]=0.0; out[25][1][1]=0.0; out[26][0][1]=9.0*l1_x*dyl1_y-9.0*l5_x*dyl1_y; out[26][1][1]=0.0; out[27][0][1]=15.0*l1_x*dyl2_y-15.0*l5_x*dyl2_y; out[27][1][1]=0.0; out[28][0][1]=21.0*l1_x*dyl3_y-21.0*l5_x*dyl3_y; out[28][1][1]=0.0; out[29][0][1]=27.0*l1_x*dyl4_y-27.0*l5_x*dyl4_y; out[29][1][1]=0.0; out[30][0][1]=0.0; out[30][1][1]=0.0; out[31][0][1]=15.0*l2_x*dyl1_y-15.0*l4_x*dyl1_y; out[31][1][1]=0.0; out[32][0][1]=25.0*l2_x*dyl2_y-25.0*l4_x*dyl2_y; out[32][1][1]=0.0; out[33][0][1]=35.0*l2_x*dyl3_y-35.0*l4_x*dyl3_y; out[33][1][1]=0.0; out[34][0][1]=45.0*l2_x*dyl4_y-45.0*l4_x*dyl4_y; out[34][1][1]=0.0; out[35][0][1]=0.0; out[35][1][1]=0.0; out[36][0][1]=21.0*l3_x*dyl1_y-21.0*l5_x*dyl1_y; out[36][1][1]=0.0; out[37][0][1]=35.0*l3_x*dyl2_y-35.0*l5_x*dyl2_y; out[37][1][1]=0.0; out[38][0][1]=49.0*l3_x*dyl3_y-49.0*l5_x*dyl3_y; out[38][1][1]=0.0; out[39][0][1]=63.0*l3_x*dyl4_y-63.0*l5_x*dyl4_y; out[39][1][1]=0.0; out[40][0][1]=0.0; out[40][1][1]=-dyl4_y; out[41][0][1]=0.0; out[41][1][1]=3.0*dyl1_y-3.0*dyl5_y; out[42][0][1]=0.0; out[42][1][1]=5.0*dyl2_y-5.0*dyl4_y; out[43][0][1]=0.0; out[43][1][1]=7.0*dyl3_y-7.0*dyl5_y; out[44][0][1]=0.0; out[44][1][1]=-3.0*l1_x*dyl4_y; out[45][0][1]=0.0; out[45][1][1]=9.0*l1_x*dyl1_y-9.0*l1_x*dyl5_y; out[46][0][1]=0.0; out[46][1][1]=15.0*l1_x*dyl2_y-15.0*l1_x*dyl4_y; out[47][0][1]=0.0; out[47][1][1]=21.0*l1_x*dyl3_y-21.0*l1_x*dyl5_y; out[48][0][1]=0.0; out[48][1][1]=-5.0*l2_x*dyl4_y; out[49][0][1]=0.0; out[49][1][1]=15.0*l2_x*dyl1_y-15.0*l2_x*dyl5_y; out[50][0][1]=0.0; out[50][1][1]=25.0*l2_x*dyl2_y-25.0*l2_x*dyl4_y; out[51][0][1]=0.0; out[51][1][1]=35.0*l2_x*dyl3_y-35.0*l2_x*dyl5_y; out[52][0][1]=0.0; out[52][1][1]=-7.0*l3_x*dyl4_y; out[53][0][1]=0.0; out[53][1][1]=21.0*l3_x*dyl1_y-21.0*l3_x*dyl5_y; out[54][0][1]=0.0; out[54][1][1]=35.0*l3_x*dyl2_y-35.0*l3_x*dyl4_y; out[55][0][1]=0.0; out[55][1][1]=49.0*l3_x*dyl3_y-49.0*l3_x*dyl5_y; out[56][0][1]=0.0; out[56][1][1]=-9.0*l4_x*dyl4_y; out[57][0][1]=0.0; out[57][1][1]=27.0*l4_x*dyl1_y-27.0*l4_x*dyl5_y; out[58][0][1]=0.0; out[58][1][1]=45.0*l4_x*dyl2_y-45.0*l4_x*dyl4_y; out[59][0][1]=0.0; out[59][1][1]=63.0*l4_x*dyl3_y-63.0*l4_x*dyl5_y; } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(size()); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); auto const& x = in[0], y = in[1]; auto l1_x = 2*x - 1; auto l2_x = x*(6*x - 6) + 1; auto l3_x = x*(x*(20*x - 30) + 12) - 1; auto l4_x = x*(x*(x*(70*x - 140) + 90) - 20) + 1; auto l5_x = x*(x*(x*(x*(252*x - 630) + 560) - 210) + 30) - 1; auto l1_y = 2*y - 1; auto l2_y = y*(6*y - 6) + 1; auto l3_y = y*(y*(20*y - 30) + 12) - 1; auto l4_y = y*(y*(y*(70*y - 140) + 90) - 20) + 1; auto l5_y = y*(y*(y*(y*(252*y - 630) + 560) - 210) + 30) - 1; if (direction == 0) { auto dxl1_x = 2.0; auto dxl2_x = 12*x - 6; auto dxl3_x = x*(60*x - 60) + 12; auto dxl4_x = x*(x*(280*x - 420) + 180) - 20; auto dxl5_x = x*(x*(x*(1260*x - 2520) + 1680) - 420) + 30; out[0][0]=sign0*(0.5*(-dxl4_x)+0.5*dxl5_x); out[0][1]=0.0; out[1][0]=-(1.5)*dxl4_x*l1_y+1.5*dxl5_x*l1_y; out[1][1]=0.0; out[2][0]=sign0*(-(2.5)*dxl4_x*l2_y+2.5*dxl5_x*l2_y); out[2][1]=0.0; out[3][0]=-(3.5)*dxl4_x*l3_y+3.5*dxl5_x*l3_y; out[3][1]=0.0; out[4][0]=sign0*(-(4.5)*dxl4_x*l4_y+4.5*dxl5_x*l4_y); out[4][1]=0.0; out[5][0]=sign1*(0.5*dxl4_x+0.5*dxl5_x); out[5][1]=0.0; out[6][0]=-(1.5)*dxl4_x*l1_y-1.5*dxl5_x*l1_y; out[6][1]=0.0; out[7][0]=sign1*(2.5*dxl4_x*l2_y+2.5*dxl5_x*l2_y); out[7][1]=0.0; out[8][0]=-(3.5)*dxl4_x*l3_y-3.5*dxl5_x*l3_y; out[8][1]=0.0; out[9][0]=sign1*(4.5*dxl4_x*l4_y+4.5*dxl5_x*l4_y); out[9][1]=0.0; out[10][0]=0.0; out[10][1]=0.0; out[11][0]=0.0; out[11][1]=1.5*dxl1_x*l4_y-1.5*dxl1_x*l5_y; out[12][0]=0.0; out[12][1]=sign2*(-(2.5)*dxl2_x*l4_y+2.5*dxl2_x*l5_y); out[13][0]=0.0; out[13][1]=3.5*dxl3_x*l4_y-3.5*dxl3_x*l5_y; out[14][0]=0.0; out[14][1]=sign2*(-(4.5)*dxl4_x*l4_y+4.5*dxl4_x*l5_y); out[15][0]=0.0; out[15][1]=0.0; out[16][0]=0.0; out[16][1]=1.5*dxl1_x*l4_y+1.5*dxl1_x*l5_y; out[17][0]=0.0; out[17][1]=sign3*(2.5*dxl2_x*l4_y+2.5*dxl2_x*l5_y); out[18][0]=0.0; out[18][1]=3.5*dxl3_x*l4_y+3.5*dxl3_x*l5_y; out[19][0]=0.0; out[19][1]=sign3*(4.5*dxl4_x*l4_y+4.5*dxl4_x*l5_y); out[20][0]=-dxl4_x; out[20][1]=0.0; out[21][0]=-3.0*dxl4_x*l1_y; out[21][1]=0.0; out[22][0]=-5.0*dxl4_x*l2_y; out[22][1]=0.0; out[23][0]=-7.0*dxl4_x*l3_y; out[23][1]=0.0; out[24][0]=-9.0*dxl4_x*l4_y; out[24][1]=0.0; out[25][0]=3.0*dxl1_x-3.0*dxl5_x; out[25][1]=0.0; out[26][0]=9.0*dxl1_x*l1_y-9.0*dxl5_x*l1_y; out[26][1]=0.0; out[27][0]=15.0*dxl1_x*l2_y-15.0*dxl5_x*l2_y; out[27][1]=0.0; out[28][0]=21.0*dxl1_x*l3_y-21.0*dxl5_x*l3_y; out[28][1]=0.0; out[29][0]=27.0*dxl1_x*l4_y-27.0*dxl5_x*l4_y; out[29][1]=0.0; out[30][0]=5.0*dxl2_x-5.0*dxl4_x; out[30][1]=0.0; out[31][0]=15.0*dxl2_x*l1_y-15.0*dxl4_x*l1_y; out[31][1]=0.0; out[32][0]=25.0*dxl2_x*l2_y-25.0*dxl4_x*l2_y; out[32][1]=0.0; out[33][0]=35.0*dxl2_x*l3_y-35.0*dxl4_x*l3_y; out[33][1]=0.0; out[34][0]=45.0*dxl2_x*l4_y-45.0*dxl4_x*l4_y; out[34][1]=0.0; out[35][0]=7.0*dxl3_x-7.0*dxl5_x; out[35][1]=0.0; out[36][0]=21.0*dxl3_x*l1_y-21.0*dxl5_x*l1_y; out[36][1]=0.0; out[37][0]=35.0*dxl3_x*l2_y-35.0*dxl5_x*l2_y; out[37][1]=0.0; out[38][0]=49.0*dxl3_x*l3_y-49.0*dxl5_x*l3_y; out[38][1]=0.0; out[39][0]=63.0*dxl3_x*l4_y-63.0*dxl5_x*l4_y; out[39][1]=0.0; out[40][0]=0.0; out[40][1]=0.0; out[41][0]=0.0; out[41][1]=0.0; out[42][0]=0.0; out[42][1]=0.0; out[43][0]=0.0; out[43][1]=0.0; out[44][0]=0.0; out[44][1]=3.0*dxl1_x-3.0*dxl1_x*l4_y; out[45][0]=0.0; out[45][1]=9.0*dxl1_x*l1_y-9.0*dxl1_x*l5_y; out[46][0]=0.0; out[46][1]=15.0*dxl1_x*l2_y-15.0*dxl1_x*l4_y; out[47][0]=0.0; out[47][1]=21.0*dxl1_x*l3_y-21.0*dxl1_x*l5_y; out[48][0]=0.0; out[48][1]=5.0*dxl2_x-5.0*dxl2_x*l4_y; out[49][0]=0.0; out[49][1]=15.0*dxl2_x*l1_y-15.0*dxl2_x*l5_y; out[50][0]=0.0; out[50][1]=25.0*dxl2_x*l2_y-25.0*dxl2_x*l4_y; out[51][0]=0.0; out[51][1]=35.0*dxl2_x*l3_y-35.0*dxl2_x*l5_y; out[52][0]=0.0; out[52][1]=7.0*dxl3_x-7.0*dxl3_x*l4_y; out[53][0]=0.0; out[53][1]=21.0*dxl3_x*l1_y-21.0*dxl3_x*l5_y; out[54][0]=0.0; out[54][1]=35.0*dxl3_x*l2_y-35.0*dxl3_x*l4_y; out[55][0]=0.0; out[55][1]=49.0*dxl3_x*l3_y-49.0*dxl3_x*l5_y; out[56][0]=0.0; out[56][1]=9.0*dxl4_x-9.0*dxl4_x*l4_y; out[57][0]=0.0; out[57][1]=27.0*dxl4_x*l1_y-27.0*dxl4_x*l5_y; out[58][0]=0.0; out[58][1]=45.0*dxl4_x*l2_y-45.0*dxl4_x*l4_y; out[59][0]=0.0; out[59][1]=63.0*dxl4_x*l3_y-63.0*dxl4_x*l5_y; } else if (direction == 1) { auto dyl1_y = 2.0; auto dyl2_y = 12*y - 6; auto dyl3_y = y*(60*y - 60) + 12; auto dyl4_y = y*(y*(280*y - 420) + 180) - 20; auto dyl5_y = y*(y*(y*(1260*y - 2520) + 1680) - 420) + 30; out[0][0]=0.0; out[0][1]=0.0; out[1][0]=-(1.5)*l4_x*dyl1_y+1.5*l5_x*dyl1_y; out[1][1]=0.0; out[2][0]=sign0*(-(2.5)*l4_x*dyl2_y+2.5*l5_x*dyl2_y); out[2][1]=0.0; out[3][0]=-(3.5)*l4_x*dyl3_y+3.5*l5_x*dyl3_y; out[3][1]=0.0; out[4][0]=sign0*(-(4.5)*l4_x*dyl4_y+4.5*l5_x*dyl4_y); out[4][1]=0.0; out[5][0]=0.0; out[5][1]=0.0; out[6][0]=-(1.5)*l4_x*dyl1_y-1.5*l5_x*dyl1_y; out[6][1]=0.0; out[7][0]=sign1*(2.5*l4_x*dyl2_y+2.5*l5_x*dyl2_y); out[7][1]=0.0; out[8][0]=-(3.5)*l4_x*dyl3_y-3.5*l5_x*dyl3_y; out[8][1]=0.0; out[9][0]=sign1*(4.5*l4_x*dyl4_y+4.5*l5_x*dyl4_y); out[9][1]=0.0; out[10][0]=0.0; out[10][1]=sign2*(0.5*(-dyl4_y)+0.5*dyl5_y); out[11][0]=0.0; out[11][1]=1.5*l1_x*dyl4_y-1.5*l1_x*dyl5_y; out[12][0]=0.0; out[12][1]=sign2*(-(2.5)*l2_x*dyl4_y+2.5*l2_x*dyl5_y); out[13][0]=0.0; out[13][1]=3.5*l3_x*dyl4_y-3.5*l3_x*dyl5_y; out[14][0]=0.0; out[14][1]=sign2*(-(4.5)*l4_x*dyl4_y+4.5*l4_x*dyl5_y); out[15][0]=0.0; out[15][1]=sign3*(0.5*dyl4_y+0.5*dyl5_y); out[16][0]=0.0; out[16][1]=1.5*l1_x*dyl4_y+1.5*l1_x*dyl5_y; out[17][0]=0.0; out[17][1]=sign3*(2.5*l2_x*dyl4_y+2.5*l2_x*dyl5_y); out[18][0]=0.0; out[18][1]=3.5*l3_x*dyl4_y+3.5*l3_x*dyl5_y; out[19][0]=0.0; out[19][1]=sign3*(4.5*l4_x*dyl4_y+4.5*l4_x*dyl5_y); out[20][0]=0.0; out[20][1]=0.0; out[21][0]=3.0*dyl1_y-3.0*l4_x*dyl1_y; out[21][1]=0.0; out[22][0]=5.0*dyl2_y-5.0*l4_x*dyl2_y; out[22][1]=0.0; out[23][0]=7.0*dyl3_y-7.0*l4_x*dyl3_y; out[23][1]=0.0; out[24][0]=9.0*dyl4_y-9.0*l4_x*dyl4_y; out[24][1]=0.0; out[25][0]=0.0; out[25][1]=0.0; out[26][0]=9.0*l1_x*dyl1_y-9.0*l5_x*dyl1_y; out[26][1]=0.0; out[27][0]=15.0*l1_x*dyl2_y-15.0*l5_x*dyl2_y; out[27][1]=0.0; out[28][0]=21.0*l1_x*dyl3_y-21.0*l5_x*dyl3_y; out[28][1]=0.0; out[29][0]=27.0*l1_x*dyl4_y-27.0*l5_x*dyl4_y; out[29][1]=0.0; out[30][0]=0.0; out[30][1]=0.0; out[31][0]=15.0*l2_x*dyl1_y-15.0*l4_x*dyl1_y; out[31][1]=0.0; out[32][0]=25.0*l2_x*dyl2_y-25.0*l4_x*dyl2_y; out[32][1]=0.0; out[33][0]=35.0*l2_x*dyl3_y-35.0*l4_x*dyl3_y; out[33][1]=0.0; out[34][0]=45.0*l2_x*dyl4_y-45.0*l4_x*dyl4_y; out[34][1]=0.0; out[35][0]=0.0; out[35][1]=0.0; out[36][0]=21.0*l3_x*dyl1_y-21.0*l5_x*dyl1_y; out[36][1]=0.0; out[37][0]=35.0*l3_x*dyl2_y-35.0*l5_x*dyl2_y; out[37][1]=0.0; out[38][0]=49.0*l3_x*dyl3_y-49.0*l5_x*dyl3_y; out[38][1]=0.0; out[39][0]=63.0*l3_x*dyl4_y-63.0*l5_x*dyl4_y; out[39][1]=0.0; out[40][0]=0.0; out[40][1]=-dyl4_y; out[41][0]=0.0; out[41][1]=3.0*dyl1_y-3.0*dyl5_y; out[42][0]=0.0; out[42][1]=5.0*dyl2_y-5.0*dyl4_y; out[43][0]=0.0; out[43][1]=7.0*dyl3_y-7.0*dyl5_y; out[44][0]=0.0; out[44][1]=-3.0*l1_x*dyl4_y; out[45][0]=0.0; out[45][1]=9.0*l1_x*dyl1_y-9.0*l1_x*dyl5_y; out[46][0]=0.0; out[46][1]=15.0*l1_x*dyl2_y-15.0*l1_x*dyl4_y; out[47][0]=0.0; out[47][1]=21.0*l1_x*dyl3_y-21.0*l1_x*dyl5_y; out[48][0]=0.0; out[48][1]=-5.0*l2_x*dyl4_y; out[49][0]=0.0; out[49][1]=15.0*l2_x*dyl1_y-15.0*l2_x*dyl5_y; out[50][0]=0.0; out[50][1]=25.0*l2_x*dyl2_y-25.0*l2_x*dyl4_y; out[51][0]=0.0; out[51][1]=35.0*l2_x*dyl3_y-35.0*l2_x*dyl5_y; out[52][0]=0.0; out[52][1]=-7.0*l3_x*dyl4_y; out[53][0]=0.0; out[53][1]=21.0*l3_x*dyl1_y-21.0*l3_x*dyl5_y; out[54][0]=0.0; out[54][1]=35.0*l3_x*dyl2_y-35.0*l3_x*dyl4_y; out[55][0]=0.0; out[55][1]=49.0*l3_x*dyl3_y-49.0*l3_x*dyl5_y; out[56][0]=0.0; out[56][1]=-9.0*l4_x*dyl4_y; out[57][0]=0.0; out[57][1]=27.0*l4_x*dyl1_y-27.0*l4_x*dyl5_y; out[58][0]=0.0; out[58][1]=45.0*l4_x*dyl2_y-45.0*l4_x*dyl4_y; out[59][0]=0.0; out[59][1]=63.0*l4_x*dyl3_y-63.0*l4_x*dyl5_y; } else { DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! \brief Polynomial order of the shape functions unsigned int order () const { return 9; } private: R sign0, sign1, sign2, sign3; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALBASIS_HH raviartthomas4cube2dlocalcoefficients.hh000066400000000000000000000025051313314431100402620ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas4cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALCOEFFICIENTS_HH #include #include #include "../../common/localkey.hh" namespace Dune { /** * \ingroup LocalLayoutImplementation * \brief Layout map for Raviart-Thomas-4 elements on quadrilaterals * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ class RT4Cube2DLocalCoefficients { public: //! \brief Standard constructor RT4Cube2DLocalCoefficients () : li(60) { for (std::size_t i = 0; i < 4; i++) { li[5*i] = LocalKey(i,1,0); li[5*i + 1] = LocalKey(i,1,1); li[5*i + 2] = LocalKey(i,1,2); li[5*i + 3] = LocalKey(i,1,3); li[5*i + 4] = LocalKey(i,1,4); } for (std::size_t i=0; i<40; i++) { li[20 + i] = LocalKey(0,0,i); } } //! \brief number of coefficients std::size_t size () const { return 60; } //! \brief get i'th index const LocalKey& localKey (std::size_t i) const { return li[i]; } private: std::vector li; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALCOEFFICIENTS_HH raviartthomas4cube2dlocalinterpolation.hh000066400000000000000000000140261313314431100405110ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomas4cube2d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALINTERPOLATION_HH #include #include namespace Dune { /** * \ingroup LocalInterpolationImplementation * \brief Second order Raviart-Thomas shape functions on the reference triangle. * * \tparam LB corresponding LocalBasis giving traits * * \nosubgrouping */ template class RT4Cube2DLocalInterpolation { public: //! \brief Standard constructor RT4Cube2DLocalInterpolation () { sign0 = sign1 = sign2 = sign3 = 1.0; } /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT4Cube2DLocalInterpolation (unsigned int s) { sign0 = sign1 = sign2 = sign3 = 1.0; if (s & 1) { sign0 *= -1.0; } if (s & 2) { sign1 *= -1.0; } if (s & 4) { sign2 *= -1.0; } if (s & 8) { sign3 *= -1.0; } n0[0] = -1.0; n0[1] = 0.0; n1[0] = 1.0; n1[1] = 0.0; n2[0] = 0.0; n2[1] = -1.0; n3[0] = 0.0; n3[1] = 1.0; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param f function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& f, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; typedef typename LB::Traits::DomainFieldType Vector; typename F::Traits::RangeType y; out.resize(60); fill(out.begin(), out.end(), 0.0); const int qOrder = 12; const QuadratureRule& rule = QuadratureRules::rule(GeometryType(GeometryType::cube,1), qOrder); for (typename QuadratureRule::const_iterator it=rule.begin(); it!=rule.end(); ++it) { Scalar qPos = it->position(); typename LB::Traits::DomainType localPos; localPos[0] = 0.0; localPos[1] = qPos; f.evaluate(localPos, y); out[0] += (y[0]*n0[0] + y[1]*n0[1])*it->weight()*sign0; out[1] += (y[0]*n0[0] + y[1]*n0[1])*(2.0*qPos - 1.0)*it->weight(); out[2] += (y[0]*n0[0] + y[1]*n0[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign0; out[3] += (y[0]*n0[0] + y[1]*n0[1])*(20.0*qPos*qPos*qPos - 30.0*qPos*qPos + 12.0*qPos - 1.0)*it->weight(); out[4] += (y[0]*n0[0] + y[1]*n0[1])*(1.0-20.0*qPos+90.0*pow(qPos,2)-140.0*pow(qPos,3)+70.0*pow(qPos,4))*it->weight()*sign0; localPos[0] = 1.0; localPos[1] = qPos; f.evaluate(localPos, y); out[5] += (y[0]*n1[0] + y[1]*n1[1])*it->weight()*sign1; out[6] += (y[0]*n1[0] + y[1]*n1[1])*(1.0 - 2.0*qPos)*it->weight(); out[7] += (y[0]*n1[0] + y[1]*n1[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign1; out[8] += (y[0]*n1[0] + y[1]*n1[1])*(-20.0*qPos*qPos*qPos + 30.0*qPos*qPos - 12.0*qPos + 1.0)*it->weight(); out[9] += (y[0]*n1[0] + y[1]*n1[1])*(1.0-20.0*qPos+90.0*pow(qPos,2)-140.0*pow(qPos,3)+70.0*pow(qPos,4))*it->weight()*sign1; localPos[0] = qPos; localPos[1] = 0.0; f.evaluate(localPos, y); out[10] += (y[0]*n2[0] + y[1]*n2[1])*it->weight()*sign2; out[11] += (y[0]*n2[0] + y[1]*n2[1])*(1.0 - 2.0*qPos)*it->weight(); out[12] += (y[0]*n2[0] + y[1]*n2[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign2; out[13] += (y[0]*n2[0] + y[1]*n2[1])*(-20.0*qPos*qPos*qPos + 30.0*qPos*qPos - 12.0*qPos + 1.0)*it->weight(); out[14] += (y[0]*n2[0] + y[1]*n2[1])*(1.0-20.0*qPos+90.0*pow(qPos,2)-140.0*pow(qPos,3)+70.0*pow(qPos,4))*it->weight()*sign2; localPos[0] = qPos; localPos[1] = 1.0; f.evaluate(localPos, y); out[15] += (y[0]*n3[0] + y[1]*n3[1])*it->weight()*sign3; out[16] += (y[0]*n3[0] + y[1]*n3[1])*(2.0*qPos - 1.0)*it->weight(); out[17] += (y[0]*n3[0] + y[1]*n3[1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*it->weight()*sign3; out[18] += (y[0]*n3[0] + y[1]*n3[1])*(20.0*qPos*qPos*qPos - 30.0*qPos*qPos + 12.0*qPos - 1.0)*it->weight(); out[19] += (y[0]*n3[0] + y[1]*n3[1])*(1.0-20.0*qPos+90.0*pow(qPos,2)-140.0*pow(qPos,3)+70.0*pow(qPos,4))*it->weight()*sign3; } const QuadratureRule& rule2 = QuadratureRules::rule(GeometryType(GeometryType::cube,2), qOrder); for (typename QuadratureRule::const_iterator it = rule2.begin(); it != rule2.end(); ++it) { FieldVector qPos = it->position(); f.evaluate(qPos, y); std::vector > l(2,std::vector (5)); l[0][0]=1.0; l[1][0]=1.0; l[0][1]=2.0*qPos[0]-1.0; l[1][1]=2.0*qPos[1]-1.0; l[0][2]=6.0*qPos[0]*qPos[0]-6.0*qPos[0]+1.0; l[1][2]=6.0*qPos[1]*qPos[1]-6.0*qPos[1]+1.0; l[0][3]=20.0*qPos[0]*qPos[0]*qPos[0] - 30.0*qPos[0]*qPos[0] + 12.0*qPos[0] - 1.0; l[1][3]=20.0*qPos[1]*qPos[1]*qPos[1] - 30.0*qPos[1]*qPos[1] + 12.0*qPos[1] - 1.0; l[0][4]=1.0-20.0*qPos[0]+90.0*pow(qPos[0],2)-140.0*pow(qPos[0],3)+70.0*pow(qPos[0],4); l[1][4]=1.0-20.0*qPos[1]+90.0*pow(qPos[1],2)-140.0*pow(qPos[1],3)+70.0*pow(qPos[1],4); for (int i=0;i<4;i++) for (int j=0;j<5;j++) out[20+i*5+j] +=y[0]*l[0][i]*l[1][j]*it->weight(); for (int i=0;i<5;i++) for (int j=0;j<4;j++) out[40+i*4+j] +=y[1]*l[0][i]*l[1][j]*it->weight(); } } private: typename LB::Traits::RangeFieldType sign0, sign1, sign2, sign3; typename LB::Traits::DomainType n0, n1, n2, n3; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomascube.hh000066400000000000000000000114461313314431100304010ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_CUBE_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_CUBE_HH #include "raviartthomas0cube2d.hh" #include "raviartthomas0cube3d.hh" #include "raviartthomas1cube2d.hh" #include "raviartthomas1cube3d.hh" #include "raviartthomas2cube2d.hh" #include "raviartthomas3cube2d.hh" #include "raviartthomas4cube2d.hh" /** * \file * \brief Convenience header that includes all available Raviart-Thomas * local finite elements for cubes. */ namespace Dune { /** * \brief Raviart-Thomas local finite elements for cubes. * * Convenience class to access all implemented Raviart-Thomas local * finite elements for cubes. * Generic Raviart-Thomas local finite elements for cubes like for * simpleces could be written. * * \ingroup RaviartThomas * * \tparam D type to represent the field in the domain. * \tparam R type to represent the field in the range. * \tparam dim dimension of the reference elements, must be 2 or 3. * \tparam order order of the element, depending on \a dim it can be 0, 1, or 2. */ template class RaviartThomasCubeLocalFiniteElement; /** * \brief Raviart-Thomas local finite elements for cubes with dimension 2 and order 0. */ template class RaviartThomasCubeLocalFiniteElement : public RT0Cube2DLocalFiniteElement { public: RaviartThomasCubeLocalFiniteElement() : RT0Cube2DLocalFiniteElement::RT0Cube2DLocalFiniteElement() {} RaviartThomasCubeLocalFiniteElement(int s) : RT0Cube2DLocalFiniteElement::RT0Cube2DLocalFiniteElement(s) {} }; /** * \brief Raviart-Thomas local finite elements for cubes with dimension 2 and order 1. */ template class RaviartThomasCubeLocalFiniteElement : public RT1Cube2DLocalFiniteElement { public: RaviartThomasCubeLocalFiniteElement() : RT1Cube2DLocalFiniteElement::RT1Cube2DLocalFiniteElement() {} RaviartThomasCubeLocalFiniteElement(int s) : RT1Cube2DLocalFiniteElement::RT1Cube2DLocalFiniteElement(s) {} }; /** * \brief Raviart-Thomas local finite elements for cubes with dimension 2 and order 2. */ template class RaviartThomasCubeLocalFiniteElement : public RT2Cube2DLocalFiniteElement { public: RaviartThomasCubeLocalFiniteElement() : RT2Cube2DLocalFiniteElement::RT2Cube2DLocalFiniteElement() {} RaviartThomasCubeLocalFiniteElement(int s) : RT2Cube2DLocalFiniteElement::RT2Cube2DLocalFiniteElement(s) {} }; /** * \brief Raviart-Thomas local finite elements for cubes with dimension 2 and order 3. */ template class RaviartThomasCubeLocalFiniteElement : public RT3Cube2DLocalFiniteElement { public: RaviartThomasCubeLocalFiniteElement() : RT3Cube2DLocalFiniteElement::RT3Cube2DLocalFiniteElement() {} RaviartThomasCubeLocalFiniteElement(int s) : RT3Cube2DLocalFiniteElement::RT3Cube2DLocalFiniteElement(s) {} }; /** * \brief Raviart-Thomas local finite elements for cubes with dimension 2 and order 4. */ template class RaviartThomasCubeLocalFiniteElement : public RT4Cube2DLocalFiniteElement { public: RaviartThomasCubeLocalFiniteElement() : RT4Cube2DLocalFiniteElement::RT4Cube2DLocalFiniteElement() {} RaviartThomasCubeLocalFiniteElement(int s) : RT4Cube2DLocalFiniteElement::RT4Cube2DLocalFiniteElement(s) {} }; /** * \brief Raviart-Thomas local finite elements for cubes with dimension 3 and order 0. */ template class RaviartThomasCubeLocalFiniteElement : public RT0Cube3DLocalFiniteElement { public: RaviartThomasCubeLocalFiniteElement() : RT0Cube3DLocalFiniteElement::RT0Cube3DLocalFiniteElement() {} RaviartThomasCubeLocalFiniteElement(int s) : RT0Cube3DLocalFiniteElement::RT0Cube3DLocalFiniteElement(s) {} }; /** * \brief Raviart-Thomas local finite elements for cubes with dimension 3 and order 1. */ template class RaviartThomasCubeLocalFiniteElement : public RT1Cube3DLocalFiniteElement { public: RaviartThomasCubeLocalFiniteElement() : RT1Cube3DLocalFiniteElement::RT1Cube3DLocalFiniteElement() {} RaviartThomasCubeLocalFiniteElement(int s) : RT1Cube3DLocalFiniteElement::RT1Cube3DLocalFiniteElement(s) {} }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_CUBE_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomassimplex.hh000066400000000000000000000035041313314431100311400ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_SIMPLEX_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_SIMPLEX_HH #include #include "raviartthomassimplex/raviartthomassimplexbasis.hh" /** * \file * \brief Raviart-Thomas local finite elements of arbitrary order * for simplices of arbitrary dimension. */ namespace Dune { /** * \brief Raviart-Thomas local finite elements of arbitrary order * for simplices of arbitrary dimension. * * These generic local finite elements are only available for * simplex geometry types. The extension to cube and prism * elements could be added. * * \ingroup RaviartThomas * * \tparam dimDomain dimension of reference elements * \tparam D domain for basis functions * \tparam R range for basis functions * \tparam SF storage field for basis matrix * \tparam CF compute field for basis matrix */ template class RaviartThomasSimplexLocalFiniteElement : public GenericLocalFiniteElement, RaviartThomasCoefficientsFactory, RaviartThomasL2InterpolationFactory > { typedef GenericLocalFiniteElement, RaviartThomasCoefficientsFactory, RaviartThomasL2InterpolationFactory > Base; public: using typename Base::Traits; /** \todo Please doc me */ RaviartThomasSimplexLocalFiniteElement(const GeometryType >, unsigned int order) : Base(gt, order) {} }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_SIMPLEX_HH dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomassimplex/000077500000000000000000000000001313314431100306155ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomassimplex/CMakeLists.txt000066400000000000000000000003301313314431100333510ustar00rootroot00000000000000install(FILES raviartthomassimplexbasis.hh raviartthomassimplexinterpolation.hh raviartthomassimplexprebasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomassimplex) raviartthomassimplexbasis.hh000066400000000000000000000012461313314431100363720ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomassimplex// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RAVIARTTHOMASBASIS_HH #define DUNE_RAVIARTTHOMASBASIS_HH #include #include #include #include "raviartthomassimplexinterpolation.hh" #include "raviartthomassimplexprebasis.hh" namespace Dune { template< unsigned int dim, class SF, class CF > struct RaviartThomasBasisFactory : public DefaultBasisFactory< RTPreBasisFactory, RaviartThomasL2InterpolationFactory, dim,dim,SF,CF > {}; } #endif // #ifndef DUNE_RAVIARTTHOMASBASIS_HH raviartthomassimplexinterpolation.hh000066400000000000000000000334601313314431100401630ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomassimplex// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASSIMPLEX_RAVIARTTHOMASSIMPLEXINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASSIMPLEX_RAVIARTTHOMASSIMPLEXINTERPOLATION_HH #include #include #include #include #include #include #include #include #include #include #include namespace Dune { // Internal Forward Declarations // ----------------------------- template < unsigned int dim > struct RaviartThomasCoefficientsFactory; template < unsigned int dim, class Field > struct RaviartThomasL2InterpolationFactory; // LocalCoefficientsContainer // -------------------------- class LocalCoefficientsContainer { typedef LocalCoefficientsContainer This; public: template LocalCoefficientsContainer ( const Setter &setter ) { setter.setLocalKeys(localKey_); } const LocalKey &localKey ( const unsigned int i ) const { assert( i < size() ); return localKey_[ i ]; } unsigned int size () const { return localKey_.size(); } private: std::vector< LocalKey > localKey_; }; // RaviartThomasCoefficientsFactoryTraits // -------------------------------------- template < unsigned int dim > struct RaviartThomasCoefficientsFactoryTraits { static const unsigned int dimension = dim; typedef const LocalCoefficientsContainer Object; typedef unsigned int Key; typedef RaviartThomasCoefficientsFactory Factory; }; // RaviartThomasCoefficientsFactory // -------------------------------- template < unsigned int dim > struct RaviartThomasCoefficientsFactory : public TopologyFactory< RaviartThomasCoefficientsFactoryTraits< dim > > { typedef RaviartThomasCoefficientsFactoryTraits< dim > Traits; template< class Topology > static typename Traits::Object *createObject( const typename Traits::Key &key ) { typedef RaviartThomasL2InterpolationFactory< dim, double > InterpolationFactory; if( !supports< Topology >( key ) ) return nullptr; typename InterpolationFactory::Object *interpolation = InterpolationFactory::template create< Topology >( key ); typename Traits::Object *localKeys = new typename Traits::Object( *interpolation ); InterpolationFactory::release( interpolation ); return localKeys; } template< class Topology > static bool supports ( const typename Traits::Key &key ) { return Impl::IsSimplex< Topology >::value; } }; // RTL2InterpolationBuilder // ------------------------ // L2 Interpolation requires: // - for element // - test basis // - for each face (dynamic) // - test basis // - normal template< unsigned int dim, class Field > struct RTL2InterpolationBuilder { static const unsigned int dimension = dim; typedef OrthonormalBasisFactory< dimension, Field > TestBasisFactory; typedef typename TestBasisFactory::Object TestBasis; typedef OrthonormalBasisFactory< dimension-1, Field > TestFaceBasisFactory; typedef typename TestFaceBasisFactory::Object TestFaceBasis; typedef FieldVector< Field, dimension > Normal; RTL2InterpolationBuilder () = default; RTL2InterpolationBuilder ( const RTL2InterpolationBuilder & ) = delete; RTL2InterpolationBuilder ( RTL2InterpolationBuilder && ) = delete; ~RTL2InterpolationBuilder () { TestBasisFactory::release( testBasis_ ); for( FaceStructure &f : faceStructure_ ) TestFaceBasisFactory::release( f.basis_ ); } unsigned int topologyId () const { return topologyId_; } GeometryType type () const { return GeometryType( topologyId(), dimension ); } unsigned int order () const { return order_; } unsigned int faceSize () const { return faceSize_; } TestBasis *testBasis () const { return testBasis_; } TestFaceBasis *testFaceBasis ( unsigned int f ) const { assert( f < faceSize() ); return faceStructure_[ f ].basis_; } const Normal &normal ( unsigned int f ) const { assert( f < faceSize() ); return *(faceStructure_[ f ].normal_); } template< class Topology > void build ( unsigned int order ) { order_ = order; topologyId_ = Topology::id; testBasis_ = (order > 0 ? TestBasisFactory::template create< Topology >( order-1 ) : nullptr); const auto &refElement = ReferenceElements< Field, dimension >::general( type() ); faceSize_ = refElement.size( 1 ); faceStructure_.reserve( faceSize_ ); for( unsigned int face = 0; face < faceSize_; ++face ) { TestFaceBasis *faceBasis = Impl::IfTopology< CreateFaceBasis, dimension-1 >::apply( refElement.type( face, 1 ).id(), order ); faceStructure_.emplace_back( faceBasis, refElement.integrationOuterNormal( face ) ); } assert( faceStructure_.size() == faceSize_ ); } private: struct FaceStructure { FaceStructure( TestFaceBasis *tfb, const Normal &n ) : basis_( tfb ), normal_( &n ) {} TestFaceBasis *basis_; const Dune::FieldVector< Field, dimension > *normal_; }; template< class FaceTopology > struct CreateFaceBasis { static TestFaceBasis *apply ( unsigned int order ) { return TestFaceBasisFactory::template create< FaceTopology >( order ); } }; std::vector< FaceStructure > faceStructure_; TestBasis *testBasis_ = nullptr; unsigned int topologyId_, order_, faceSize_; }; // RaviartThomasL2Interpolation // ---------------------------- /** * \class RaviartThomasL2Interpolation * \brief An L2-based interpolation for Raviart Thomas * **/ template< unsigned int dimension, class F> class RaviartThomasL2Interpolation : public InterpolationHelper< F ,dimension > { typedef RaviartThomasL2Interpolation< dimension, F > This; typedef InterpolationHelper Base; public: typedef F Field; typedef RTL2InterpolationBuilder Builder; RaviartThomasL2Interpolation() : order_(0), size_(0) {} template< class Function, class Fy > void interpolate ( const Function &function, std::vector< Fy > &coefficients ) const { coefficients.resize(size()); typename Base::template Helper,true> func( function,coefficients ); interpolate(func); } template< class Basis, class Matrix > void interpolate ( const Basis &basis, Matrix &matrix ) const { matrix.resize( size(), basis.size() ); typename Base::template Helper func( basis,matrix ); interpolate(func); } unsigned int order() const { return order_; } unsigned int size() const { return size_; } template void build( unsigned int order ) { size_ = 0; order_ = order; builder_.template build(order_); if (builder_.testBasis()) size_ += dimension*builder_.testBasis()->size(); for ( unsigned int f=0; fsize(); } void setLocalKeys(std::vector< LocalKey > &keys) const { keys.resize(size()); unsigned int row = 0; for (unsigned int f=0; fsize(); ++i,++row) keys[row] = LocalKey(f,1,i); } if (builder_.testBasis()) for (unsigned int i=0; isize()*dimension; ++i,++row) keys[row] = LocalKey(0,0,i); assert( row == size() ); } protected: template< class Func, class Container, bool type > void interpolate ( typename Base::template Helper &func ) const { const Dune::GeometryType geoType( builder_.topologyId(), dimension ); std::vector< Field > testBasisVal; for (unsigned int i=0; i FaceQuadrature; typedef Dune::QuadratureRules FaceQuadratureRules; typedef Dune::ReferenceElements< Field, dimension > RefElements; typedef Dune::ReferenceElement< Field, dimension > RefElement; typedef typename RefElement::template Codim< 1 >::Geometry Geometry; const RefElement &refElement = RefElements::general( geoType ); for (unsigned int f=0; fsize()); const Geometry &geometry = refElement.template geometry< 1 >( f ); const Dune::GeometryType subGeoType( geometry.type().id(), dimension-1 ); const FaceQuadrature &faceQuad = FaceQuadratureRules::rule( subGeoType, 2*order_+2 ); const unsigned int quadratureSize = faceQuad.size(); for( unsigned int qi = 0; qi < quadratureSize; ++qi ) { if (dimension>1) builder_.testFaceBasis(f)->template evaluate<0>(faceQuad[qi].position(),testBasisVal); else testBasisVal[0] = 1.; fillBnd( row, testBasisVal, func.evaluate( geometry.global( faceQuad[qi].position() ) ), builder_.normal(f), faceQuad[qi].weight(), func); } row += builder_.testFaceBasis(f)->size(); } // element dofs if (builder_.testBasis()) { testBasisVal.resize(builder_.testBasis()->size()); typedef Dune::QuadratureRule Quadrature; typedef Dune::QuadratureRules QuadratureRules; const Quadrature &elemQuad = QuadratureRules::rule( geoType, 2*order_+1 ); const unsigned int quadratureSize = elemQuad.size(); for( unsigned int qi = 0; qi < quadratureSize; ++qi ) { builder_.testBasis()->template evaluate<0>(elemQuad[qi].position(),testBasisVal); fillInterior( row, testBasisVal, func.evaluate(elemQuad[qi].position()), elemQuad[qi].weight(), func ); } row += builder_.testBasis()->size()*dimension; } assert(row==size()); } private: /** /brief evaluate boundary functionals **/ template void fillBnd (unsigned int startRow, const MVal &mVal, const RTVal &rtVal, const FieldVector &normal, const Field &weight, Matrix &matrix) const { const unsigned int endRow = startRow+mVal.size(); typename RTVal::const_iterator rtiter = rtVal.begin(); for ( unsigned int col = 0; col < rtVal.size() ; ++rtiter,++col) { Field cFactor = (*rtiter)*normal; typename MVal::const_iterator miter = mVal.begin(); for (unsigned int row = startRow; row!=endRow; ++miter, ++row ) { matrix.add(row,col, (weight*cFactor)*(*miter) ); } assert( miter == mVal.end() ); } } template void fillInterior (unsigned int startRow, const MVal &mVal, const RTVal &rtVal, Field weight, Matrix &matrix) const { const unsigned int endRow = startRow+mVal.size()*dimension; typename RTVal::const_iterator rtiter = rtVal.begin(); for ( unsigned int col = 0; col < rtVal.size() ; ++rtiter,++col) { typename MVal::const_iterator miter = mVal.begin(); for (unsigned int row = startRow; row!=endRow; ++miter,row+=dimension ) { for (unsigned int i=0; i struct RaviartThomasL2InterpolationFactoryTraits { static const unsigned int dimension = dim; typedef unsigned int Key; typedef const RaviartThomasL2Interpolation Object; typedef RaviartThomasL2InterpolationFactory Factory; }; template < unsigned int dim, class Field > struct RaviartThomasL2InterpolationFactory : public TopologyFactory< RaviartThomasL2InterpolationFactoryTraits > { typedef RaviartThomasL2InterpolationFactoryTraits Traits; typedef RTL2InterpolationBuilder Builder; typedef typename Traits::Object Object; typedef typename std::remove_const::type NonConstObject; template static typename Traits::Object *createObject( const typename Traits::Key &key ) { if ( !supports(key) ) return 0; NonConstObject *interpol = new NonConstObject(); interpol->template build(key); return interpol; } template< class Topology > static bool supports ( const typename Traits::Key &key ) { return Impl::IsSimplex::value; } }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASSIMPLEX_RAVIARTTHOMASSIMPLEXINTERPOLATION_HH raviartthomassimplexprebasis.hh000066400000000000000000000102671313314431100371040ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/raviartthomas/raviartthomassimplex// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_RAVIARTTHOMASPREBASIS_HH #define DUNE_RAVIARTTHOMASPREBASIS_HH #include #include #include #include namespace Dune { template struct RTPreBasisFactory; template struct RTPreBasisFactoryTraits { static const unsigned int dimension = dim; typedef MonomialBasisProvider MBasisFactory; typedef typename MBasisFactory::Object MBasis; typedef StandardEvaluator EvalMBasis; typedef PolynomialBasisWithMatrix > Basis; typedef const Basis Object; typedef unsigned int Key; typedef RTPreBasisFactory Factory; }; template < class Topology, class Field > struct RTVecMatrix; template struct RTPreBasisFactory : public TopologyFactory< RTPreBasisFactoryTraits< dim, Field > > { typedef RTPreBasisFactoryTraits< dim, Field > Traits; static const unsigned int dimension = dim; typedef typename Traits::Object Object; typedef typename Traits::Key Key; template struct EvaluationBasisFactory { typedef MonomialBasisProvider Type; }; template< class Topology > static Object *createObject ( const Key &order ) { RTVecMatrix vecMatrix(order); typename Traits::MBasis *mbasis = Traits::MBasisFactory::template create(order+1); typename std::remove_const::type *tmBasis = new typename std::remove_const::type(*mbasis); tmBasis->fill(vecMatrix); return tmBasis; } }; template struct RTVecMatrix { static const unsigned int dim = Topology::dimension; typedef MultiIndex MI; typedef MonomialBasis MIBasis; RTVecMatrix(unsigned int order) { MIBasis basis(order+1); FieldVector< MI, dim > x; for( unsigned int i = 0; i < dim; ++i ) x[ i ].set( i, 1 ); std::vector< MI > val( basis.size() ); basis.evaluate( x, val ); col_ = basis.size(); unsigned int notHomogen = 0; if (order>0) notHomogen = basis.sizes()[order-1]; unsigned int homogen = basis.sizes()[order]-notHomogen; row_ = (notHomogen*dim+homogen*(dim+1))*dim; row1_ = basis.sizes()[order]*dim*dim; mat_ = new Field*[row_]; int row = 0; for (unsigned int i=0; i void row( const unsigned int row, Vector &vec ) const { const unsigned int N = cols(); assert( vec.size() == N ); for (unsigned int i=0; i #include dune-localfunctions-2.5.1/dune/localfunctions/refined/000077500000000000000000000000001313314431100230575ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/refined/CMakeLists.txt000066400000000000000000000003051313314431100256150ustar00rootroot00000000000000add_subdirectory(common) add_subdirectory(refinedp0) add_subdirectory(refinedp1) install(FILES refinedp0.hh refinedp1.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/refined) dune-localfunctions-2.5.1/dune/localfunctions/refined/common/000077500000000000000000000000001313314431100243475ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/refined/common/CMakeLists.txt000066400000000000000000000001701313314431100271050ustar00rootroot00000000000000install(FILES refinedsimplexlocalbasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/refined/common) dune-localfunctions-2.5.1/dune/localfunctions/refined/common/refinedsimplexlocalbasis.hh000066400000000000000000000245201313314431100317460ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_REFINED_SIMPLEX_LOCALBASIS_HH #define DUNE_REFINED_SIMPLEX_LOCALBASIS_HH /** \file \brief Contains a base class for LocalBasis classes based on uniform refinement */ #include #include #include namespace Dune { template class RefinedSimplexLocalBasis { protected: RefinedSimplexLocalBasis() { DUNE_THROW(Dune::NotImplemented,"RefinedSimplexLocalBasis not implemented for dim > 3."); } }; /**@ingroup LocalBasisImplementation \brief Base class for LocalBasis classes based on uniform refinement in 1D; provides numbering and local coordinates of subelements \tparam D Type to represent the field in the domain. \nosubgrouping */ template class RefinedSimplexLocalBasis { protected: /** \brief Protected default constructor so this class can only be instantiated as a base class. */ RefinedSimplexLocalBasis() {} /** \brief Get the number of the subelement containing a given point. * * The subelements are ordered according to * * 0 1 * |-------:-------| * * \param[in] global Coordinates in the reference element * \returns Number of the subtriangle containing global */ static int getSubElement(const FieldVector& global) { if (global[0] <= 0.5) return 0; else if (global[0] <= 1.0) return 1; DUNE_THROW(InvalidStateException, "no subelement defined"); } /** \brief Get local coordinates in the subelement \param[in] global Coordinates in the reference element \param[out] subElement Number of the subelement containing global \param[out] local The local coordinates in the subelement */ static void getSubElement(const FieldVector& global, int& subElement, FieldVector& local) { if (global[0] <= 0.5) { subElement = 0; local[0] = 2.0 * global[0]; return; } subElement = 1; local[0] = 2.0 * global[0] - 1.0; } }; /**@ingroup LocalBasisImplementation \brief Base class for LocalBasis classes based on uniform refinement in 2D; provides numbering and local coordinates of subelements Shape functions like these are necessary for hierarchical error estimators for certain nonlinear problems. \tparam D Type to represent the field in the domain. \nosubgrouping */ template class RefinedSimplexLocalBasis { protected: /** \brief Protected default constructor so this class can only be instantiated as a base class. */ RefinedSimplexLocalBasis() {} /** \brief Get the number of the subtriangle containing a given point. * * The triangles are ordered according to * \verbatim |\ |2\ |--\ |\3|\ |0\|1\ ------ \endverbatim * * \param[in] global Coordinates in the reference triangle * \returns Number of the subtriangle containing global */ static int getSubElement(const FieldVector& global) { if (global[0] + global[1] <= 0.5) return 0; else if (global[0] >= 0.5) return 1; else if (global[1] >= 0.5) return 2; return 3; } /** \brief Get local coordinates in the subtriangle \param[in] global Coordinates in the reference triangle \param[out] subElement Number of the subtriangle containing global \param[out] local The local coordinates in the subtriangle */ static void getSubElement(const FieldVector& global, int& subElement, FieldVector& local) { if (global[0] + global[1] <= 0.5) { subElement = 0; local[0] = 2*global[0]; local[1] = 2*global[1]; return; } else if (global[0] >= 0.5) { subElement = 1; local[0] = 2*global[0]-1; local[1] = 2*global[1]; return; } else if (global[1] >= 0.5) { subElement = 2; local[0] = 2*global[0]; local[1] = 2*global[1]-1; return; } subElement = 3; local[0] = -2 * global[0] + 1; local[1] = -2 * global[1] + 1; } }; /**@ingroup LocalBasisImplementation \brief Base class for LocalBasis classes based on uniform refinement in 3D; provides numbering and local coordinates of subelements Shape functions like these are necessary for hierarchical error estimators for certain nonlinear problems. \tparam D Type to represent the field in the domain. \nosubgrouping */ template class RefinedSimplexLocalBasis { protected: /** \brief Protected default constructor so this class can only be instantiated as a base class. */ RefinedSimplexLocalBasis() {} /** \brief Get the number of the subsimplex containing a given point in the reference element * * Defining the following points in the reference simplex * * 0: (0.0, 0.0, 0.0) * 1: (1.0, 0.0, 0.0) * 2: (0.0, 1.0, 0.0) * 3: (0.0, 0.0, 1.0) * 4: (0.5, 0.0, 0.0) * 5: (0.5, 0.5, 0.0) * 6: (0.0, 0.5, 0.0) * 7: (0.0, 0.0, 0.5) * 8: (0.5, 0.0, 0.5) * 9: (0.0, 0.5, 0.5) * * The subsimplices are numbered according to * * 0: 0467 - * 1: 4158 |_ "cut off" vertices * 2: 6529 | * 3: 7893 - * * 4: 6487 - * 5: 4568 |_ octahedron partition * 6: 6897 | * 7: 6895 - * * \param[in] global Coordinates in the reference simplex * \returns Number of the subsimplex containing global */ static int getSubElement(const FieldVector& global) { if (global[0] + global[1] + global[2] <= 0.5) return 0; else if (global[0] >= 0.5) return 1; else if (global[1] >= 0.5) return 2; else if (global[2] >= 0.5) return 3; else if ((global[0] + global[1] <= 0.5)and (global[1] + global[2] <= 0.5)) return 4; else if ((global[0] + global[1] >= 0.5)and (global[1] + global[2] <= 0.5)) return 5; else if ((global[0] + global[1] <= 0.5)and (global[1] + global[2] >= 0.5)) return 6; else if ((global[0] + global[1] >= 0.5)and (global[1] + global[2] >= 0.5)) return 7; DUNE_THROW(InvalidStateException, "no subelement defined"); } /** \brief Get local coordinates in the subsimplex \param[in] global Coordinates in the reference simplex \param[out] subElement Number of the subsimplex containing global \param[out] local The local coordinates in the subsimplex */ static void getSubElement(const FieldVector& global, int& subElement, FieldVector& local) { if (global[0] + global[1] + global[2] <= 0.5) { subElement = 0; local = global; local *= 2.0; return; } else if (global[0] >= 0.5) { subElement = 1; local = global; local[0] -= 0.5; local *= 2.0; return; } else if (global[1] >= 0.5) { subElement = 2; local = global; local[1] -= 0.5; local *= 2.0; return; } else if (global[2] >= 0.5) { subElement = 3; local = global; local[2] -= 0.5; local *= 2.0; return; } else if ((global[0] + global[1] <= 0.5)and (global[1] + global[2] <= 0.5)) { subElement = 4; local[0] = 2.0 * global[1]; local[1] = 2.0 * (0.5 - global[0] - global[1]); local[2] = 2.0 * (-0.5 + global[0] + global[1] + global[2]); // Dune::FieldMatrix A(0.0); // A[0][1] = 2.0; // A[1][0] = -2.0; // A[1][1] = -2.0; // A[2][0] = 2.0; // A[2][1] = 2.0; // A[2][2] = 2.0; // A.mv(global,local); // local[1] += 1.0; // local[2] -= 1.0; return; } else if ((global[0] + global[1] >= 0.5)and (global[1] + global[2] <= 0.5)) { subElement = 5; local[0] = 2.0 * (0.5 - global[0]); local[1] = 2.0 * (0.5 - global[1] - global[2]); local[2] = 2.0 * global[2]; // Dune::FieldMatrix A(0.0); // A[0][0] = -2.0; // A[1][1] = -2.0; // A[1][2] = -2.0; // A[2][2] = 2.0; // A.mv(global,local); // local[0] += 1.0; // local[1] += 1.0; return; } else if ((global[0] + global[1] <= 0.5)and (global[1] + global[2] >= 0.5)) { subElement = 6; local[0] = 2.0 * (0.5 - global[0] - global[1]); local[1] = 2.0 * global[0]; local[2] = 2.0 * (-0.5 + global[1] + global[2]); // Dune::FieldMatrix A(0.0); // A[0][0] = -2.0; // A[0][1] = -2.0; // A[1][0] = 2.0; // A[2][1] = 2.0; // A[2][2] = 2.0; // A.mv(global,local); // local[0] += 1.0; // local[2] -= 1.0; return; } else if ((global[0] + global[1] >= 0.5)and (global[1] + global[2] >= 0.5)) { subElement = 7; local[0] = 2.0 * (-0.5 + global[1] + global[2]); local[1] = 2.0 * (0.5 - global[1]); local[2] = 2.0 * (-0.5 + global[0] + global[1]); // Dune::FieldMatrix A(0.0); // A[0][1] = 2.0; // A[0][2] = 2.0; // A[1][1] = -2.0; // A[2][0] = 2.0; // A[2][1] = 2.0; // A.mv(global,local); // local[0] -= 1.0; // local[1] += 1.0; // local[2] -= 1.0; return; } DUNE_THROW(InvalidStateException, "no subelement defined"); } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp0.hh000066400000000000000000000127551313314431100252660ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_REFINED_P0_LOCALFINITEELEMENT_HH #define DUNE_REFINED_P0_LOCALFINITEELEMENT_HH #include #include #include #include "refinedp0/refinedp0localbasis.hh" #include "refinedp0/refinedp0localcoefficients.hh" #include "refinedp0/refinedp0localinterpolation.hh" /** \file \brief Piecewise P0 finite element */ namespace Dune { /** \brief Local finite element that is piecewise P0 on a once uniformly refined reference geometry */ template class RefinedP0LocalFiniteElement { RefinedP0LocalFiniteElement() {} public: // We steal the p0 traits since they exist for all dim. // This allows to instantiate the type and access the Traits. typedef typename P0LocalFiniteElement::Traits Traits; }; /** \brief Local finite element that is piecewise P0 on a once uniformly refined reference geometry */ template class RefinedP0LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits< RefinedP0LocalBasis, RefinedP0LocalCoefficients<1>, RefinedP0LocalInterpolation > > Traits; /** \todo Please doc me ! */ RefinedP0LocalFiniteElement () { gt.makeLine(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis_.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } RefinedP0LocalFiniteElement * clone () const { return new RefinedP0LocalFiniteElement(*this); } private: RefinedP0LocalBasis basis_; RefinedP0LocalCoefficients<1> coefficients_; RefinedP0LocalInterpolation > interpolation_; GeometryType gt; }; /** \brief Local finite element that is piecewise P0 on a once uniformly refined reference geometry */ template class RefinedP0LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits< RefinedP0LocalBasis, RefinedP0LocalCoefficients<2>, RefinedP0LocalInterpolation > > Traits; /** \todo Please doc me ! */ RefinedP0LocalFiniteElement () { gt.makeTriangle(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis_.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } RefinedP0LocalFiniteElement * clone () const { return new RefinedP0LocalFiniteElement(*this); } private: RefinedP0LocalBasis basis_; RefinedP0LocalCoefficients<2> coefficients_; RefinedP0LocalInterpolation > interpolation_; GeometryType gt; }; /** \brief Local finite element that is piecewise P0 on a once uniformly refined reference geometry */ template class RefinedP0LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits< RefinedP0LocalBasis, RefinedP0LocalCoefficients<3>, RefinedP0LocalInterpolation > > Traits; /** \todo Please doc me ! */ RefinedP0LocalFiniteElement () { gt.makeTetrahedron(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis_.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } RefinedP0LocalFiniteElement * clone () const { return new RefinedP0LocalFiniteElement(*this); } private: RefinedP0LocalBasis basis_; RefinedP0LocalCoefficients<3> coefficients_; RefinedP0LocalInterpolation > interpolation_; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp0/000077500000000000000000000000001313314431100247335ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp0/CMakeLists.txt000066400000000000000000000002711313314431100274730ustar00rootroot00000000000000install(FILES refinedp0localbasis.hh refinedp0localcoefficients.hh refinedp0localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/refined/refinedp0) dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp0/refinedp0localbasis.hh000066400000000000000000000056621313314431100311760ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_REFINED_P0_LOCALBASIS_HH #define DUNE_REFINED_P0_LOCALBASIS_HH #include #include #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Uniformly refined constant shape functions on a unit simplex in R^dim This shape function set mimicks the P0 shape functions that you would get on a uniformly refined grid. Hence these shape functions are only piecewise constant! Shape functions like these are necessary for hierarchical error estimators for certain nonlinear problems. The functions are associated with the subelements as defined in RefinedSimplexLocalBasis \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \tparam dim Dimension of domain space \nosubgrouping */ template class RefinedP0LocalBasis : public RefinedSimplexLocalBasis { // 2 to the k-th power enum {N = 1<,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return N; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { int subElement = this->getSubElement(in); out.resize(N); for(int i=0; i& out) const // return value { out.resize(N); for(int i=0; i& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i] = 0; } } /** \brief Polynomial order of the shape functions * * Doesn't really apply: these shape functions are only piecewise constant */ unsigned int order () const { return 0; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp0/refinedp0localcoefficients.hh000066400000000000000000000020601313314431100325230ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_REFINED_P0_LOCALCOEFFICIENTS_HH #define DUNE_REFINED_P0_LOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for RefinedP0 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ template class RefinedP0LocalCoefficients { // 2 to the k-th power enum {N = 1< localKeys_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp0/refinedp0localinterpolation.hh000066400000000000000000000076611313314431100327650ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_REFINED_P0_LOCALINTERPOLATION_HH #define DUNE_REFINED_P0_LOCALINTERPOLATION_HH #include namespace Dune { template class RefinedP0LocalInterpolation {}; template class RefinedP0LocalInterpolation > { typedef RefinedP0LocalBasis LB; typedef typename LB::Traits::DomainType DT; public: RefinedP0LocalInterpolation() : interpolationPoints_(2) { // Interpolation is done by evaluating at the halved segments centers interpolationPoints_[0][0] = 1.0/4.0; interpolationPoints_[1][0] = 3.0/4.0; } template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; out.resize(interpolationPoints_.size()); for (size_t i = 0; i < out.size(); ++i) { f.evaluate(interpolationPoints_[i], y); out[i] = y; } } private: std::vector
interpolationPoints_; }; template class RefinedP0LocalInterpolation > { typedef RefinedP0LocalBasis LB; typedef typename LB::Traits::DomainType DT; public: RefinedP0LocalInterpolation() : interpolationPoints_(4) { // Interpolation is done by evaluating at the subtriangle centers interpolationPoints_[0][0] = 1.0/6; interpolationPoints_[0][1] = 1.0/6; interpolationPoints_[1][0] = 4.0/6; interpolationPoints_[1][1] = 1.0/6; interpolationPoints_[2][0] = 1.0/6; interpolationPoints_[2][1] = 4.0/6; interpolationPoints_[3][0] = 2.0/6; interpolationPoints_[3][1] = 2.0/6; } template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; out.resize(interpolationPoints_.size()); for (size_t i = 0; i < out.size(); ++i) { f.evaluate(interpolationPoints_[i], y); out[i] = y; } } private: std::vector
interpolationPoints_; }; template class RefinedP0LocalInterpolation > { typedef RefinedP0LocalBasis LB; typedef typename LB::Traits::DomainType DT; public: RefinedP0LocalInterpolation() : interpolationPoints_(8) { // Interpolation is done by evaluating at the subtriangle centers interpolationPoints_[0][0] = 1.0/8; interpolationPoints_[0][1] = 1.0/8; interpolationPoints_[0][2] = 1.0/8; interpolationPoints_[1][0] = 5.0/8; interpolationPoints_[1][1] = 1.0/8; interpolationPoints_[1][2] = 1.0/8; interpolationPoints_[2][0] = 1.0/8; interpolationPoints_[2][1] = 5.0/8; interpolationPoints_[2][2] = 1.0/8; interpolationPoints_[3][0] = 1.0/8; interpolationPoints_[3][1] = 1.0/8; interpolationPoints_[3][2] = 5.0/8; interpolationPoints_[4][0] = 1.0/4; interpolationPoints_[4][1] = 1.0/8; interpolationPoints_[4][2] = 1.0/4; interpolationPoints_[5][0] = 3.0/8; interpolationPoints_[5][1] = 1.0/4; interpolationPoints_[5][2] = 1.0/8; interpolationPoints_[6][0] = 1.0/8; interpolationPoints_[6][1] = 1.0/4; interpolationPoints_[6][2] = 3.0/8; interpolationPoints_[7][0] = 1.0/4; interpolationPoints_[7][1] = 3.0/8; interpolationPoints_[7][2] = 1.0/4; } template void interpolate (const F& f, std::vector& out) const { typename LB::Traits::RangeType y; out.resize(interpolationPoints_.size()); for (size_t i = 0; i < out.size(); ++i) { f.evaluate(interpolationPoints_[i], y); out[i] = y; } } private: std::vector
interpolationPoints_; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp1.hh000066400000000000000000000122721313314431100252610ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_REFINED_P1_LOCALFINITEELEMENT_HH #define DUNE_REFINED_P1_LOCALFINITEELEMENT_HH #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { /** \todo Please doc me ! */ template class RefinedP1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, Pk1DLocalCoefficients<2>, Pk1DLocalInterpolation > > Traits; /** \todo Please doc me ! */ RefinedP1LocalFiniteElement () { gt.makeLine(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } RefinedP1LocalFiniteElement * clone () const { return new RefinedP1LocalFiniteElement(*this); } private: RefinedP1LocalBasis basis; Pk1DLocalCoefficients<2> coefficients; Pk1DLocalInterpolation > interpolation; GeometryType gt; }; /** \todo Please doc me ! */ template class RefinedP1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, Pk2DLocalCoefficients<2>, Pk2DLocalInterpolation > > Traits; /** \todo Please doc me ! */ RefinedP1LocalFiniteElement () { gt.makeTriangle(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } RefinedP1LocalFiniteElement * clone () const { return new RefinedP1LocalFiniteElement(*this); } private: RefinedP1LocalBasis basis; Pk2DLocalCoefficients<2> coefficients; Pk2DLocalInterpolation > interpolation; GeometryType gt; }; /** \todo Please doc me ! */ template class RefinedP1LocalFiniteElement { public: /** \todo Please doc me ! */ typedef LocalFiniteElementTraits, Pk3DLocalCoefficients<2>, Pk3DLocalInterpolation > > Traits; /** \todo Please doc me ! */ RefinedP1LocalFiniteElement () { gt.makeTetrahedron(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return basis; } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } /** \todo Please doc me ! */ GeometryType type () const { return gt; } RefinedP1LocalFiniteElement* clone () const { return new RefinedP1LocalFiniteElement(*this); } private: RefinedP1LocalBasis basis; Pk3DLocalCoefficients<2> coefficients; Pk3DLocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp1/000077500000000000000000000000001313314431100247345ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp1/CMakeLists.txt000066400000000000000000000001661313314431100274770ustar00rootroot00000000000000install(FILES refinedp1localbasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/refined/refinedp1) dune-localfunctions-2.5.1/dune/localfunctions/refined/refinedp1/refinedp1localbasis.hh000066400000000000000000000600241313314431100311710ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_REFINED_P1_LOCALBASIS_HH #define DUNE_REFINED_P1_LOCALBASIS_HH /** \file \brief Linear Lagrange shape functions on a uniformly refined reference element */ #include #include #include namespace Dune { template class RefinedP1LocalBasis : public RefinedSimplexLocalBasis { public: RefinedP1LocalBasis() { DUNE_THROW(Dune::NotImplemented,"RefinedP1LocalBasis not implemented for dim > 3."); } }; /**@ingroup LocalBasisImplementation \brief Uniformly refined linear Lagrange shape functions in 1D. 1D IMPLEMENTATION IS NOT TESTED (the LocalElement for 1D does not exist due to lack of P21D elements) This shape function set mimicks the P1 shape functions that you would get on a uniformly refined grid. Hence these shape functions are only piecewise linear! The data layout is identical to P2 shape functions. Shape functions like these are necessary for hierarchical error estimators for certain nonlinear problems. The functions are associated to points by: f_0 ~ (0.0) f_1 ~ (1.0) f_2 ~ (0.5) \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class RefinedP1LocalBasis : public RefinedSimplexLocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 3; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(3); int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); switch (subElement) { case 0 : out[0] = 1 - local[0]; out[1] = local[0]; out[2] = 0; break; case 1 : out[0] = 0; out[1] = 1 - local[0]; out[2] = local[0]; break; } } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(3); int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); switch (subElement) { case 0 : out[0][0][0] = -2; out[1][0][0] = 2; out[2][0][0] = 0; break; case 1 : out[0][0][0] = 0; out[1][0][0] = -2; out[2][0][0] = 2; break; } } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = order[0]; if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { out.resize(3); int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); switch (subElement) { case 0: out[0] = -2; out[1] = 2; out[2] = 0; break; case 1: out[0] = 0; out[1] = -2; out[2] = 2; break; } } else { out.resize(3); out[0] = out[1] = out[2] = 0; } } /** \brief Polynomial order of the shape functions Doesn't really apply: these shape functions are only piecewise linear */ unsigned int order () const { return 1; } }; /**@ingroup LocalBasisImplementation \brief Uniformly refined linear Lagrange shape functions on the triangle. This shape function set mimicks the P1 shape functions that you would get on a uniformly refined grid. Hence these shape functions are only piecewise linear! The data layout is identical to P2 shape functions. Shape functions like these are necessary for hierarchical error estimators for certain nonlinear problems. The functions are associated to points by: f_0 ~ (0.0, 0.0) f_1 ~ (0.5, 0.0) f_2 ~ (1.0, 0.0) f_3 ~ (0.0, 0.5) f_4 ~ (0.5, 0.5) f_5 ~ (0.0, 1.0) \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class RefinedP1LocalBasis : public RefinedSimplexLocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 6; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(6); int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); switch (subElement) { case 0 : out[0] = 1 - local[0] - local[1]; out[1] = local[0]; out[2] = 0; out[3] = local[1]; out[4] = 0; out[5] = 0; break; case 1 : out[0] = 0; out[1] = 1 - local[0] - local[1]; out[2] = local[0]; out[3] = 0; out[4] = local[1]; out[5] = 0; break; case 2 : out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1 - local[0] - local[1]; out[4] = local[0]; out[5] = local[1]; break; case 3 : out[0] = 0; out[1] = local[1]; out[2] = 0; out[3] = local[0]; out[4] = 1 - local[0] - local[1]; out[5] = 0; } } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(6); int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); switch (subElement) { case 0 : out[0][0][0] = -2; out[0][0][1] = -2; out[1][0][0] = 2; out[1][0][1] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[3][0][0] = 0; out[3][0][1] = 2; out[4][0][0] = 0; out[4][0][1] = 0; out[5][0][0] = 0; out[5][0][1] = 0; break; case 1 : out[0][0][0] = 0; out[0][0][1] = 0; out[1][0][0] = -2; out[1][0][1] = -2; out[2][0][0] = 2; out[2][0][1] = 0; out[3][0][0] = 0; out[3][0][1] = 0; out[4][0][0] = 0; out[4][0][1] = 2; out[5][0][0] = 0; out[5][0][1] = 0; break; case 2 : out[0][0][0] = 0; out[0][0][1] = 0; out[1][0][0] = 0; out[1][0][1] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[3][0][0] = -2; out[3][0][1] = -2; out[4][0][0] = 2; out[4][0][1] = 0; out[5][0][0] = 0; out[5][0][1] = 2; break; case 3 : out[0][0][0] = 0; out[0][0][1] = 0; out[1][0][0] = 0; out[1][0][1] = -2; out[2][0][0] = 0; out[2][0][1] = 0; out[3][0][0] = -2; out[3][0][1] = 0; out[4][0][0] = 2; out[4][0][1] = 2; out[5][0][0] = 0; out[5][0][1] = 0; } } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i] = 0; switch (direction) { case 0: // direction == 0 switch (subElement) { case 0 : out[0] = -2; out[1] = 2; break; case 1 : out[1] = -2; out[2] = 2; break; case 2 : out[3] = -2; out[4] = 2; break; case 3 : out[3] = -2; out[4] = 2; } break; case 1: // direction == 1 switch (subElement) { case 0 : out[0] = -2; out[3] = 2; break; case 1 : out[1] = -2; out[4] = 2; break; case 2 : out[3] = -2; out[5] = 2; break; case 3 : out[1] = -2; out[4] = 2; } break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i] = 0; } } /** \brief Polynomial order of the shape functions Doesn't really apply: these shape functions are only piecewise linear */ unsigned int order () const { return 1; } }; /**@ingroup LocalBasisImplementation \brief Uniformly refined linear Lagrange shape functions on the 3D-simplex (tetrahedron). This shape function set mimicks the P1 shape functions that you would get on a uniformly refined grid. Hence these shape functions are only piecewise linear! The data layout is identical to P2 shape functions. Shape functions like these are necessary for hierarchical error estimators for certain nonlinear problems. The functions are associated to points by: f_0 ~ (0.0, 0.0, 0.0) f_1 ~ (1.0, 0.0, 0.0) f_2 ~ (0.0, 1.0, 0.0) f_3 ~ (0.0, 0.0, 1.0) f_4 ~ (0.5, 0.0, 0.0) f_5 ~ (0.5, 0.5, 0.0) f_6 ~ (0.0, 0.5, 0.0) f_7 ~ (0.0, 0.0, 0.5) f_8 ~ (0.5, 0.0, 0.5) f_9 ~ (0.0, 0.5, 0.5) \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class RefinedP1LocalBasis : public RefinedSimplexLocalBasis { public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief number of shape functions unsigned int size () const { return 10; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(10); int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); switch (subElement) { case 0 : out[0] = 1 - local[0] - local[1] - local[2]; out[1] = local[0]; out[2] = 0; out[3] = local[1]; out[4] = 0; out[5] = 0; out[6] = local[2]; out[7] = 0; out[8] = 0; out[9] = 0; break; case 1 : out[0] = 0; out[1] = 1 - local[0] - local[1] -local[2]; out[2] = local[0]; out[3] = 0; out[4] = local[1]; out[5] = 0; out[6] = 0; out[7] = local[2]; out[8] = 0; out[9] = 0; break; case 2 : out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1 - local[0] - local[1] -local[2]; out[4] = local[0]; out[5] = local[1]; out[6] = 0; out[7] = 0; out[8] = local[2]; out[9] = 0; break; case 3 : out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 0; out[6] = 1 - local[0] - local[1] -local[2]; out[7] = local[0]; out[8] = local[1]; out[9] = local[2]; break; case 4 : out[0] = 0; out[1] = 1 - local[0] - local[1] -local[2]; out[2] = 0; out[3] = local[0]; out[4] = 0; out[5] = 0; out[6] = local[1]; out[7] = local[2]; out[8] = 0; out[9] = 0; break; case 5 : out[0] = 0; out[1] = local[1]; out[2] = 0; out[3] = local[0]; out[4] = 1 - local[0] - local[1] -local[2]; out[5] = 0; out[6] = 0; out[7] = local[2]; out[8] = 0; out[9] = 0; break; case 6 : out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1 - local[0] - local[1] -local[2]; out[4] = 0; out[5] = 0; out[6] = local[0]; out[7] = local[1]; out[8] = local[2]; out[9] = 0; break; case 7 : out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1 - local[0] - local[1] -local[2]; out[4] = local[2]; out[5] = 0; out[6] = 0; out[7] = local[1]; out[8] = local[0]; out[9] = 0; break; } } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType& in, // position std::vector& out) const // return value { out.resize(10); int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); switch (subElement) { case 0 : out[0][0][0] = -2; out[0][0][1] = -2; out[0][0][2] = -2; out[1][0][0] = 2; out[1][0][1] = 0; out[1][0][2] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = 0; out[3][0][1] = 2; out[3][0][2] = 0; out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[6][0][0] = 0; out[6][0][1] = 0; out[6][0][2] = 2; out[7][0][0] = 0; out[7][0][1] = 0; out[7][0][2] = 0; out[8][0][0] = 0; out[8][0][1] = 0; out[8][0][2] = 0; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 0; break; case 1 : out[0][0][0] = 0; out[0][0][1] = 0; out[0][0][2] = 0; out[1][0][0] = -2; out[1][0][1] = -2; out[1][0][2] = -2; out[2][0][0] = 2; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = 0; out[3][0][1] = 0; out[3][0][2] = 0; out[4][0][0] = 0; out[4][0][1] = 2; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[6][0][0] = 0; out[6][0][1] = 0; out[6][0][2] = 0; out[7][0][0] = 0; out[7][0][1] = 0; out[7][0][2] = 2; out[8][0][0] = 0; out[8][0][1] = 0; out[8][0][2] = 0; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 0; break; case 2 : out[0][0][0] = 0; out[0][0][1] = 0; out[0][0][2] = 0; out[1][0][0] = 0; out[1][0][1] = 0; out[1][0][2] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = -2; out[3][0][1] = -2; out[3][0][2] = -2; out[4][0][0] = 2; out[4][0][1] = 0; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 2; out[5][0][2] = 0; out[6][0][0] = 0; out[6][0][1] = 0; out[6][0][2] = 0; out[7][0][0] = 0; out[7][0][1] = 0; out[7][0][2] = 0; out[8][0][0] = 0; out[8][0][1] = 0; out[8][0][2] = 2; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 0; break; case 3 : out[0][0][0] = 0; out[0][0][1] = 0; out[0][0][2] = 0; out[1][0][0] = 0; out[1][0][1] = 0; out[1][0][2] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = 0; out[3][0][1] = 0; out[3][0][2] = 0; out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[6][0][0] = -2; out[6][0][1] = -2; out[6][0][2] = -2; out[7][0][0] = 2; out[7][0][1] = 0; out[7][0][2] = 0; out[8][0][0] = 0; out[8][0][1] = 2; out[8][0][2] = 0; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 2; break; case 4 : out[0][0][0] = 0; out[0][0][1] = 0; out[0][0][2] = 0; out[1][0][0] = 0; out[1][0][1] = -2; out[1][0][2] = -2; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = 0; out[3][0][1] = 2; out[3][0][2] = 0; out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[6][0][0] = -2; out[6][0][1] = -2; out[6][0][2] = 0; out[7][0][0] = 2; out[7][0][1] = 2; out[7][0][2] = 2; out[8][0][0] = 0; out[8][0][1] = 0; out[8][0][2] = 0; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 0; break; case 5 : out[0][0][0] = 0; out[0][0][1] = 0; out[0][0][2] = 0; out[1][0][0] = 0; out[1][0][1] = -2; out[1][0][2] = -2; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = -2; out[3][0][1] = 0; out[3][0][2] = 0; out[4][0][0] = 2; out[4][0][1] = 2; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[6][0][0] = 0; out[6][0][1] = 0; out[6][0][2] = 0; out[7][0][0] = 0; out[7][0][1] = 0; out[7][0][2] = 2; out[8][0][0] = 0; out[8][0][1] = 0; out[8][0][2] = 0; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 0; break; case 6 : out[0][0][0] = 0; out[0][0][1] = 0; out[0][0][2] = 0; out[1][0][0] = 0; out[1][0][1] = 0; out[1][0][2] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = 0; out[3][0][1] = 0; out[3][0][2] = -2; out[4][0][0] = 0; out[4][0][1] = 0; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[6][0][0] = -2; out[6][0][1] = -2; out[6][0][2] = 0; out[7][0][0] = 2; out[7][0][1] = 0; out[7][0][2] = 0; out[8][0][0] = 0; out[8][0][1] = 2; out[8][0][2] = 2; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 0; break; case 7 : out[0][0][0] = 0; out[0][0][1] = 0; out[0][0][2] = 0; out[1][0][0] = 0; out[1][0][1] = 0; out[1][0][2] = 0; out[2][0][0] = 0; out[2][0][1] = 0; out[2][0][2] = 0; out[3][0][0] = -2; out[3][0][1] = -2; out[3][0][2] = -2; out[4][0][0] = 2; out[4][0][1] = 2; out[4][0][2] = 0; out[5][0][0] = 0; out[5][0][1] = 0; out[5][0][2] = 0; out[6][0][0] = 0; out[6][0][1] = 0; out[6][0][2] = 0; out[7][0][0] = 0; out[7][0][1] = -2; out[7][0][2] = 0; out[8][0][0] = 0; out[8][0][1] = 2; out[8][0][2] = 2; out[9][0][0] = 0; out[9][0][1] = 0; out[9][0][2] = 0; break; } } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder == 1) { int subElement; typename Traits::DomainType local; this->getSubElement(in, subElement, local); auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i] = 0; switch (direction) { case 0: // direction == 0 switch (subElement) { case 0 : out[0] = -2; out[1] = 2; break; case 1 : out[1] = -2; out[2] = 2; break; case 2 : out[3] = -2; out[4] = 2; break; case 3 : out[6] = -2; out[7] = 2; break; case 4 : out[6] = -2; out[7] = 2; break; case 5 : out[3] = -2; out[4] = 2; break; case 6 : out[6] = -2; out[7] = 2; break; case 7 : out[3] = -2; out[4] = 2; break; } break; case 1: // direction == 1 switch (subElement) { case 0 : out[0] = -2; out[3] = 2; break; case 1 : out[1] = -2; out[4] = 2; break; case 2 : out[3] = -2; out[5] = 2; break; case 3 : out[6] = -2; out[8] = 2; break; case 4 : out[1] = -2; out[3] = 2; out[6] = -2; break; case 5 : out[1] = -2; out[4] = 2; break; case 6 : out[6] = -2; out[8] = 2; break; case 7 : out[3] = -2; out[4] = 2; out[7] = -2; out[8] = 2; break; } break; case 2: // direction == 2 switch (subElement) { case 0 : out[0] = -2; out[6] = 2; break; case 1 : out[1] = -2; out[7] = 2; break; case 2 : out[3] = -2; out[8] = 2; break; case 3 : out[6] = -2; out[9] = 2; break; case 4 : out[1] = -2; out[7] = 2; break; case 5 : out[1] = -2; out[7] = 2; break; case 6 : out[3] = -2; out[8] = 2; break; case 7 : out[3] = -2; out[8] = 2; break; } break; default: DUNE_THROW(RangeError, "Component out of range."); } } else { out.resize(size()); for (std::size_t i = 0; i < size(); ++i) out[i] = 0; } } /** \brief Polynomial order of the shape functions * Doesn't really apply: these shape functions are only piecewise linear */ unsigned int order () const { return 1; } }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/test/000077500000000000000000000000001313314431100224225ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/test/CMakeLists.txt000066400000000000000000000041471313314431100251700ustar00rootroot00000000000000dune_add_test(SOURCES testgenericfem.cc) dune_add_test(SOURCES lagrangeshapefunctiontest.cc) dune_add_test(SOURCES monomialshapefunctiontest.cc) dune_add_test(SOURCES virtualshapefunctiontest.cc) dune_add_test(SOURCES test-edges0.5.cc) dune_add_test(SOURCES test-localfe.cc) dune_add_test(SOURCES test-monomial) dune_add_test(SOURCES test-pk2d.cc) dune_add_test(SOURCES test-power-monomial.cc) dune_add_test(SOURCES test-q1.cc) dune_add_test(SOURCES test-q2.cc) dune_add_test(NAME test-lagrange1 SOURCES test-lagrange.cc COMPILE_DEFINITIONS TOPOLOGY=Pyramid) dune_add_test(NAME test-lagrange2 SOURCES test-lagrange.cc COMPILE_DEFINITIONS "TOPOLOGY=Pyramid >") dune_add_test(NAME test-lagrange3 SOURCES test-lagrange.cc COMPILE_DEFINITIONS "TOPOLOGY=Pyramid > >") dune_add_test(NAME test-orthonormal1 SOURCES test-orthonormal.cc COMPILE_DEFINITIONS TOPOLOGY=Pyramid) dune_add_test(NAME test-orthonormal2 SOURCES test-orthonormal.cc COMPILE_DEFINITIONS "TOPOLOGY=Pyramid >") dune_add_test(NAME test-orthonormal3 SOURCES test-orthonormal.cc COMPILE_DEFINITIONS "TOPOLOGY=Pyramid > >") dune_add_test(NAME test-raviartthomassimplex1 SOURCES test-raviartthomassimplex.cc COMPILE_DEFINITIONS TOPOLOGY=Pyramid) dune_add_test(NAME test-raviartthomassimplex2 SOURCES test-raviartthomassimplex.cc COMPILE_DEFINITIONS "TOPOLOGY=Pyramid >") dune_add_test(NAME test-raviartthomassimplex3 SOURCES test-raviartthomassimplex.cc COMPILE_DEFINITIONS "TOPOLOGY=Pyramid > >") dune_add_test(NAME test-raviartthomassimplex-all SOURCES test-raviartthomassimplex.cc) dune_add_test(NAME test-lagrange-all SOURCES test-lagrange.cc TIMEOUT 600) dune_add_test(NAME test-orthonormal-all SOURCES test-orthonormal.cc) dune-localfunctions-2.5.1/dune/localfunctions/test/geometries.hh000066400000000000000000000133351313314431100251130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: // This header is not part of the official Dune API and might be subject // to change. You can use this header to test external finite element // implementations, but be warned that your tests might break with future // Dune versions. #ifndef DUNE_LOCALFUNCTIONS_TEST_GEOMETRIES_HH #define DUNE_LOCALFUNCTIONS_TEST_GEOMETRIES_HH #include #include #include #include #include #include template class TestGeometries; template class TestGeometries : public std::vector > { static const std::size_t dim = 0; public: typedef Dune::MultiLinearGeometry Geometry; TestGeometries() { Dune::GeometryType gt; std::vector > coords; gt.makeVertex(); coords.resize(1); this->push_back(Geometry(gt, coords)); } const Geometry &get(const Dune::GeometryType >) const { for(std::size_t i = 0; i < this->size(); ++i) if((*this)[i].type() == gt) return (*this)[i]; DUNE_THROW(Dune::NotImplemented, "No predefined test-geometry in " "dimension " << dim << " for GeometryType " << gt); } }; template class TestGeometries : public std::vector > { static const std::size_t dim = 1; public: typedef Dune::MultiLinearGeometry Geometry; TestGeometries() { Dune::GeometryType gt; std::vector > coords; gt.makeLine(); coords.resize(2); coords[0][0] = -.3; coords[1][0] = .7; this->push_back(Geometry(gt, coords)); } const Geometry &get(const Dune::GeometryType >) const { for(std::size_t i = 0; i < this->size(); ++i) if((*this)[i].type() == gt) return (*this)[i]; DUNE_THROW(Dune::NotImplemented, "No predefined test-geometry in " "dimension " << dim << " for GeometryType " << gt); } }; template class TestGeometries : public std::vector > { static const std::size_t dim = 2; public: typedef Dune::MultiLinearGeometry Geometry; TestGeometries() { Dune::GeometryType gt; std::vector > coords; gt.makeTriangle(); coords.resize(3); coords[0][0] = -.5; coords[0][1] = -.5; coords[1][0] = .5; coords[1][1] = -.5; coords[2][0] = 0 ; coords[2][1] = .5; this->push_back(Geometry(gt, coords)); gt.makeQuadrilateral(); coords.resize(4); coords[0][0] = -.5; coords[0][1] = 0; coords[1][0] = 0 ; coords[1][1] = -.5; coords[2][0] = .5; coords[2][1] = 0; coords[3][0] = 0 ; coords[3][1] = .5; this->push_back(Geometry(gt, coords)); } const Geometry &get(const Dune::GeometryType >) const { for(std::size_t i = 0; i < this->size(); ++i) if((*this)[i].type() == gt) return (*this)[i]; DUNE_THROW(Dune::NotImplemented, "No predefined test-geometry in " "dimension " << dim << " for GeometryType " << gt); } }; template class TestGeometries : public std::vector > { static const std::size_t dim = 3; public: typedef Dune::MultiLinearGeometry Geometry; TestGeometries() { Dune::GeometryType gt; std::vector > coords; gt.makeTetrahedron(); coords.resize(4); coords[0][0] = -.5; coords[0][1] = -.5; coords[0][2] = -.5; coords[1][0] = .5; coords[1][1] = -.5; coords[1][2] = -.5; coords[2][0] = 0 ; coords[2][1] = .5; coords[2][2] = -.5; coords[3][0] = 0 ; coords[3][1] = 0 ; coords[3][2] = .5; this->push_back(Geometry(gt, coords)); gt.makePyramid(); coords.resize(5); coords[0][0] = -.5; coords[0][1] = 0; coords[0][2] = -.5; coords[1][0] = 0 ; coords[1][1] = -.5; coords[1][2] = -.5; coords[2][0] = .5; coords[2][1] = 0; coords[2][2] = -.5; coords[3][0] = 0 ; coords[3][1] = .5; coords[3][2] = -.5; coords[4][0] = .1; coords[4][1] = .1; coords[4][2] = .1; this->push_back(Geometry(gt, coords)); gt.makePrism(); coords.resize(6); coords[0][0] = -.6; coords[0][1] = -.5; coords[0][2] = -.4; coords[1][0] = .5; coords[1][1] = -.6; coords[1][2] = -.5; coords[2][0] = .1; coords[2][1] = .5; coords[2][2] = -.6; coords[3][0] = -.5; coords[3][1] = -.4; coords[3][2] = .5; coords[4][0] = .4; coords[4][1] = -.5; coords[4][2] = .6; coords[5][0] = 0 ; coords[5][1] = .4; coords[5][2] = .5; this->push_back(Geometry(gt, coords)); gt.makeHexahedron(); coords.resize(8); coords[0][0] = -.7; coords[0][1] = -.6; coords[0][2] = -.5; coords[1][0] = .4; coords[1][1] = -.3; coords[1][2] = -.7; coords[2][0] = -.6; coords[2][1] = .5; coords[2][2] = -.4; coords[3][0] = .3; coords[3][1] = .7; coords[3][2] = -.6; coords[4][0] = -.5; coords[4][1] = -.4; coords[4][2] = .3; coords[5][0] = .7; coords[5][1] = -.6; coords[5][2] = .5; coords[6][0] = -.4; coords[6][1] = .3; coords[6][2] = .7; coords[7][0] = .6; coords[7][1] = .5; coords[7][2] = .4; this->push_back(Geometry(gt, coords)); } const Geometry &get(const Dune::GeometryType >) const { for(std::size_t i = 0; i < this->size(); ++i) if((*this)[i].type() == gt) return (*this)[i]; DUNE_THROW(Dune::NotImplemented, "No predefined test-geometry in " "dimension " << dim << " for GeometryType " << gt); } }; #endif // DUNE_LOCALFUNCTIONS_TEST_GEOMETRIES_HH dune-localfunctions-2.5.1/dune/localfunctions/test/lagrangeshapefunctiontest.cc000066400000000000000000000136001313314431100302000ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include #include #include #include #include /** \file \brief Performs some tests for the Pk shape functions */ bool success = true; double epsilon = 1e-14; double sqrt_epsilon = std::sqrt(epsilon); using namespace Dune; // Generate list of Lagrange points for dim-dimensional simplex template void getPkTestPoints(unsigned order, unsigned level, std::vector >& test_points) { for (unsigned i = 0; i <= order - level; ++i) { std::vector > test_points_lower_dim; getPkTestPoints(order, level + i, test_points_lower_dim); double coord = double(i) / order; for (unsigned j = 0; j < test_points_lower_dim.size(); ++j) { FieldVector pos; for (int k = 0; k < dim-1; ++k) pos[k] = test_points_lower_dim[j][k]; pos[dim-1] = coord; test_points.push_back(pos); } } } // Template specialization to terminate recursion template <> void getPkTestPoints(unsigned order, unsigned level, std::vector >& test_points) { FieldVector pos; test_points.push_back(pos); } template void testPk(const FE& local_fe) { typedef typename FE::Traits::LocalBasisType::Traits LBTraits; const int dim = FE::Traits::LocalBasisType::Traits::dimDomain; const unsigned order = local_fe.localBasis().order(); std::vector > values; std::vector > test_points; getPkTestPoints(order, 0, test_points); for (unsigned n = 0; n < test_points.size(); ++n) { FieldVector pos = test_points[n]; ////////////////////////////////////////////////////////////////// // Verfiy that shape functions fulfill \phi_i(x_j) = \delta_{ij} // We assume that the shape functions are ordered corresponding // to the test points returned by getPkTestPoints() ////////////////////////////////////////////////////////////////// local_fe.localBasis().evaluateFunction(pos, values); for (unsigned i = 0; i < values.size(); ++i) if (std::abs(values[i] - double(i==n)) > epsilon) { std::cerr << "Bug in shape function in local finite element type" << typeid(FE).name() << std::endl; std::cerr << "Shape function " << n << " has value " << values[i] << " at position " << pos << " while " << double(i==n) << " was expected" << std::endl; success = false; } ////////////////////////////////////////////////////////////////// // Check the partial derivatives by comparing them // to finite difference approximations ////////////////////////////////////////////////////////////////// // Get the shape function derivatives at pos std::vector jacobians; local_fe.localBasis().evaluateJacobian(pos, jacobians); // Loop over all axes for (int k=0; k upPos = pos; FieldVector downPos = pos; upPos[k] += sqrt_epsilon; downPos[k] -= sqrt_epsilon; std::vector > upValues, downValues; local_fe.localBasis().evaluateFunction(upPos, upValues); local_fe.localBasis().evaluateFunction(downPos, downValues); // Loop over all shape functions in this set for (unsigned j=0; j sqrt_epsilon) { std::cerr << "Bug in shape function in local finite element type " << typeid(FE).name() << std::endl; std::cerr << " of order " << order << "." << std::endl; std::cerr << " Shape function derivative differs " << "significantly from FD approximation" << std::endl; std::cerr << " Shape function " << j << " at position " << pos << ": derivative in direction " << k << " is " << derivative << ", but " << finiteDiff << " is expected." << std::endl; success = false; } } } } } int main (int argc, char *argv[]) try { #if __linux__ #if (!defined __INTEL_COMPILER || __INTEL_COMPILER >= 1010) feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW); #endif #endif P1LocalFiniteElement p11d; testPk(p11d); P1LocalFiniteElement p12d; testPk(p12d); P1LocalFiniteElement p13d; testPk(p13d); // P23DLocalFiniteElement does not fulfill above assumption on the // ordering of the shape functions // P23DLocalFiniteElement p23d; // testPk(p23d); Pk2DLocalFiniteElement pk12d; testPk(pk12d); Pk2DLocalFiniteElement pk22d; testPk(pk22d); Pk2DLocalFiniteElement pk32d; testPk(pk32d); Pk2DLocalFiniteElement pk42d; testPk(pk42d); Pk3DLocalFiniteElement pk13d; testPk(pk13d); Pk3DLocalFiniteElement pk23d; testPk(pk23d); Pk3DLocalFiniteElement pk33d; testPk(pk33d); Pk3DLocalFiniteElement pk43d; testPk(pk43d); return success ? 0 : 1; } catch (Exception e) { std::cerr << e << std::endl; return 1; } dune-localfunctions-2.5.1/dune/localfunctions/test/monomialshapefunctiontest.cc000066400000000000000000000127711313314431100302430ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include /** \file \brief Performs some tests for the monomial shape functions */ bool success = true; double epsilon = 1e-8; using namespace Dune; template void testShapeFunctionDerivative(const GeometryType& type) { MonomialLocalFiniteElement shapeFunctionSet(type); typedef typename MonomialLocalFiniteElement::Traits::LocalBasisType::Traits LBTraits; // //////////////////////////////////////////////////////////// // Check the partial derivatives by comparing them // to finite difference approximations // //////////////////////////////////////////////////////////// // A set of test points const QuadratureRule quad = QuadratureRules::rule(type,order); for (size_t i=0; i& testPoint = quad[i].position(); // Get the shape function derivatives there std::vector jacobians; shapeFunctionSet.localBasis().evaluateJacobian(testPoint, jacobians); // Loop over all shape functions in this set for (unsigned int j=0; j upPos = testPoint; FieldVector downPos = testPoint; upPos[k] += epsilon; downPos[k] -= epsilon; std::vector > upValues, downValues; shapeFunctionSet.localBasis().evaluateFunction(upPos, upValues); shapeFunctionSet.localBasis().evaluateFunction(downPos, downValues); double finiteDiff = (upValues[j] - downValues[j]) / (2*epsilon); // Check if (std::abs(derivative-finiteDiff) > epsilon) { std::cerr << "Bug in shape function of order " << order << " for " << type << "." << std::endl; std::cerr << "Shape function derivative does not agree with FD approximation" << std::endl; std::cerr << "Shape function " << j << " at position " << testPoint << ": derivative in direction " << k << " is " << derivative << ", but " << finiteDiff << " is expected." << std::endl; success = false; } } } } } template void testShapeFunctionValue(const GeometryType& gt, const Dune::FieldVector &pos, int comp, double expected) { MonomialLocalFiniteElement shapeFunctionSet(gt); std::vector > out; shapeFunctionSet.localBasis().evaluateFunction(pos, out); if(std::abs(out[comp][0]-expected) > epsilon) { std::cerr << "Bug in shape function of dimension " << dim << " and order " << order << " for " << gt << "." << std::endl; std::cerr << "Value of shape function number " << comp << " at position " << pos << " is " << out[comp][0] << " but " << expected << " was expected." << std::endl; success = false; } } int main (int argc, char *argv[]) { try { GeometryType gt; { // dim=1 Dune::FieldVector pos; gt.makeLine(); pos[0] = 0; testShapeFunctionValue<1,2>(gt, pos, 0, 1); testShapeFunctionValue<1,2>(gt, pos, 1, 0); testShapeFunctionValue<1,2>(gt, pos, 2, 0); pos[0] = .5; testShapeFunctionValue<1,2>(gt, pos, 0, 1); testShapeFunctionValue<1,2>(gt, pos, 1, .5); testShapeFunctionValue<1,2>(gt, pos, 2, .25); pos[0] = 1; testShapeFunctionValue<1,2>(gt, pos, 0, 1); testShapeFunctionValue<1,2>(gt, pos, 1, 1); testShapeFunctionValue<1,2>(gt, pos, 2, 1); } { // dim=2 Dune::FieldVector pos; gt.makeQuadrilateral(); pos[0] = 0; pos[1] = 0; testShapeFunctionValue<2,1>(gt, pos, 0, 1); testShapeFunctionValue<2,1>(gt, pos, 1, 0); testShapeFunctionValue<2,1>(gt, pos, 2, 0); pos[0] = .5; pos[1] = .5; testShapeFunctionValue<2,1>(gt, pos, 0, 1); testShapeFunctionValue<2,1>(gt, pos, 1, .5); testShapeFunctionValue<2,1>(gt, pos, 2, .5); pos[0] = 1; pos[1] = 1; testShapeFunctionValue<2,1>(gt, pos, 0, 1); testShapeFunctionValue<2,1>(gt, pos, 1, 1); testShapeFunctionValue<2,1>(gt, pos, 2, 1); } // Test shape functions for the 1d segment gt.makeLine(); testShapeFunctionDerivative<1,1>(gt); testShapeFunctionDerivative<1,2>(gt); gt.makeTriangle(); testShapeFunctionDerivative<2,1>(gt); gt.makeQuadrilateral(); testShapeFunctionDerivative<2,1>(gt); gt.makeTetrahedron(); testShapeFunctionDerivative<3,1>(gt); gt.makeHexahedron(); testShapeFunctionDerivative<3,1>(gt); gt.makePyramid(); testShapeFunctionDerivative<3,1>(gt); gt.makePrism(); testShapeFunctionDerivative<3,1>(gt); // gt.makeCube(4); // testShapeFunctionDerivative<4,1>(gt); return success ? 0 : 1; } catch (const Exception &e) { std::cout << e << std::endl; throw; } } dune-localfunctions-2.5.1/dune/localfunctions/test/test-edges0.5.cc000066400000000000000000000031741313314431100252250ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "geometries.hh" #include "test-fe.hh" template void testEdgeS0_5(int &result) { // tolerance for floating-point comparisons static const double eps = 1e-9; // stepsize for numerical differentiation static const double delta = 1e-5; std::cout << "== Checking global-valued EdgeS0_5 elements (with " << "dim=" << dim << ")" << std::endl; Dune::GeometryType gt; gt.makeSimplex(dim); typedef TestGeometries TestGeos; static const TestGeos testGeos; typedef typename TestGeos::Geometry Geometry; const Geometry &geo = testGeos.get(gt); static_assert(dim <= 3, "Need to update vertexIds array for dim > 3"); std::size_t vertexIds[] = {0, 1, 2, 3}; Dune::GeneralVertexOrder vo(gt, vertexIds+0, vertexIds+dim+1); Dune::EdgeS0_5FiniteElementFactory feFactory; bool success = testFE(geo, feFactory.make(geo, vo), eps, delta); if(success && result != 1) result = 0; else result = 1; } int main(int argc, char** argv) { try { int result = 77; testEdgeS0_5<2>(result); testEdgeS0_5<3>(result); return result; } catch (const Dune::Exception& e) { std::cout << e << std::endl; throw; } } dune-localfunctions-2.5.1/dune/localfunctions/test/test-fe.hh000066400000000000000000000220611313314431100243130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: // This header is not part of the official Dune API and might be subject // to change. You can use this header to test external finite element // implementations, but be warned that your tests might break with future // Dune versions. #ifndef DUNE_LOCALFUNCTIONS_TEST_TEST_FE_HH #define DUNE_LOCALFUNCTIONS_TEST_TEST_FE_HH #include #include #include #include #include #include #include #include #include #include #include // This class defines a local finite element function. // It is determined by a local finite element and // representing the local basis and a coefficient vector. // This provides the evaluate method needed by the interpolate() // method. template class FEFunction { typedef typename FE::Traits::Basis::Traits::DomainLocal DomainLocal; typedef typename FE::Traits::Basis::Traits::Range Range; const FE& fe; public: typedef typename FE::Traits::Basis::Traits::RangeField CT; std::vector coeff; FEFunction(const FE& fe_) : fe(fe_) { resetCoefficients(); } void resetCoefficients() { coeff.resize(fe.basis().size()); for(std::size_t i=0; i yy; fe.basis().evaluateFunction(x, yy); y = 0.0; for (std::size_t i=0; i bool testInterpolation(const FE& fe, double eps, int n=5) { bool success = true; FEFunction f(fe); std::vector::CT> coeff; for(int i=0; i() << ":" << std::endl; std::cout << " Interpolation vector has size " << coeff.size() << std::endl; std::cout << " Basis has size " << fe.basis().size() << std::endl; std::cout << std::endl; success = false; // skip rest of loop since that depends on matching sizes continue; } // Check if interpolation weights are equal to coefficients for(std::size_t j=0; j eps*(std::max(std::abs(f.coeff[j]), 1.0)) ) { std::cout << std::setprecision(16); std::cout << "Bug in LocalInterpolation for finite element type " << Dune::className() << ":" << std::endl; std::cout << " Interpolation weight " << j << " differs by " << std::abs(coeff[j]-f.coeff[j]) << " from coefficient of " << "linear combination." << std::endl; std::cout << std::endl; success = false; } } } return success; } // check whether Jacobian agrees with FD approximation /** * \param geo The geometry the finite element is tested on. * \param fe The finite element to test. * \param eps Tolerance for comparing floating-point values. When comparing * numerical derivatives, this is divided by \c delta to yield an * even bigger tolerance. * \param delta Stepsize to use when doing numerical derivatives. * \param order The Jacobian is checked at a number of quadrature points. * This parameter determines the order of the quatrature rule * used to obtain the quadrature points. */ template bool testJacobian(const Geo &geo, const FE& fe, double eps, double delta, std::size_t order = 2) { typedef typename FE::Traits::Basis Basis; typedef typename Basis::Traits::DomainField DF; static const std::size_t dimDLocal = Basis::Traits::dimDomainLocal; typedef typename Basis::Traits::DomainLocal DomainLocal; static const std::size_t dimDGlobal = Basis::Traits::dimDomainGlobal; static const std::size_t dimR = Basis::Traits::dimRange; typedef typename Basis::Traits::Range Range; typedef typename Basis::Traits::Jacobian Jacobian; bool success = true; // //////////////////////////////////////////////////////////// // Check the partial derivatives by comparing them // to finite difference approximations // //////////////////////////////////////////////////////////// // A set of test points const Dune::QuadratureRule quad = Dune::QuadratureRules::rule(fe.type(),order); // Loop over all quadrature points for (std::size_t i=0; i < quad.size(); i++) { // Get a test point const DomainLocal& testPoint = quad[i].position(); // Get the shape function derivatives there std::vector jacobians; fe.basis().evaluateJacobian(testPoint, jacobians); if(jacobians.size() != fe.basis().size()) { std::cout << "Bug in evaluateJacobianGlobal() for finite element type " << Dune::className() << ":" << std::endl; std::cout << " Jacobian vector has size " << jacobians.size() << std::endl; std::cout << " Basis has size " << fe.basis().size() << std::endl; std::cout << std::endl; return false; } Dune::FieldMatrix geoJT = geo.jacobianTransposed(testPoint); // Loop over all shape functions in this set for (std::size_t j=0; j localJacobian(0); for(std::size_t k = 0; k < dimR; ++k) for(std::size_t l = 0; l < dimDGlobal; ++l) for(std::size_t m = 0; m < dimDLocal; ++m) localJacobian[k][m] += jacobians[j][k][l] * geoJT[m][l]; // Loop over all local directions for (std::size_t m = 0; m < dimDLocal; ++m) { // Compute an approximation to the derivative by finite differences DomainLocal upPos = testPoint; DomainLocal downPos = testPoint; upPos[m] += delta; downPos[m] -= delta; std::vector upValues, downValues; fe.basis().evaluateFunction(upPos, upValues); fe.basis().evaluateFunction(downPos, downValues); //Loop over all components for(std::size_t k = 0; k < dimR; ++k) { // The current partial derivative, just for ease of notation double derivative = localJacobian[k][m]; double finiteDiff = (upValues[j][k] - downValues[j][k]) / (2*delta); // Check if ( std::abs(derivative-finiteDiff) > eps/delta*(std::max(std::abs(finiteDiff), 1.0)) ) { std::cout << std::setprecision(16); std::cout << "Bug in evaluateJacobian() for finite element type " << Dune::className() << ":" << std::endl; std::cout << " Shape function derivative does not agree with " << "FD approximation" << std::endl; std::cout << " Shape function " << j << " component " << k << " at position " << testPoint << ": derivative in " << "local direction " << m << " is " << derivative << ", but " << finiteDiff << " is " << "expected." << std::endl; std::cout << std::endl; success = false; } } //Loop over all components } // Loop over all local directions } // Loop over all shape functions in this set } // Loop over all quadrature points return success; } // call tests for given finite element template bool testFE(const Geo &geo, const FE& fe, double eps, double delta, unsigned order = 2) { bool success = true; success = testInterpolation(fe, eps) and success; success = testJacobian(geo, fe, eps, delta, order) and success; return success; } #endif // DUNE_LOCALFUNCTIONS_TEST_TEST_FE_HH dune-localfunctions-2.5.1/dune/localfunctions/test/test-lagrange.cc000066400000000000000000000116721313314431100254750ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include #include /** * \file * \brief Performs some tests for the generic Lagrange * shape functions on simplices. * * The topology can be chosen at compile time by setting TOPOLOGY * to a string like * \code * Pyramid > > * \endcode * which generates a 2d simplex. If TOPOLOGY is not set, all * topologies up to 4d are tested. Note, this may lead to prolonged * compiler runs. * * For debugging purpuse the functions and the derivatives can be * printed. You have to define the macro TEST_OUTPUT_FUNCTIONS to * activate this function. */ #if HAVE_GMP typedef Dune::GMPField< 128 > StorageField; typedef Dune::GMPField< 512 > ComputeField; #else typedef double StorageField; typedef double ComputeField; #endif template bool test(const Basis &basis, const Points &points, bool verbose) { bool ret = true; std::vector< Dune::FieldVector< double, 1 > > y( basis.size() ); for( unsigned int index = 0; index < points.size(); ++index ) { if (verbose) std::cout << index << " " << points[ index ].point() << " " << points[ index ].localKey() << std::endl; basis.evaluate( points[ index ].point(), y ); bool first = true; for( unsigned int i = 0; i < y.size(); ++i ) { if( fabs( y[ i ] - double( i == index ) ) > 1e-10 ) { if (first) { std::cout << "ERROR: " << index << " -> " << "x = " << points[ index ].point() << " (codim = " << points[ index ].localKey().codim() << ", " << "subentity = " << points[ index ].localKey().subEntity() << ", " << "index = " << points[ index ].localKey().index() << "):" << std::endl; first = false; } if (1) std::cout << " y[ " << i << " ] = " << y[ i ] << " " << " error : " << fabs( y[ i ] - double( i == index ) ) << std::endl; ret = false; } } } return ret; } template bool test(unsigned int order, bool verbose = false) { typedef Dune::LagrangeBasisFactory BasisFactory; typedef Dune::LagrangeCoefficientsFactory< Dune::EquidistantPointSet, Topology::dimension,double > LagrangeCoefficientsFactory; bool ret = true; for (unsigned int o = 0; o <= order; ++o) { const typename LagrangeCoefficientsFactory::Object *pointsPtr = LagrangeCoefficientsFactory::template create< Topology >( o ); if ( pointsPtr == 0) continue; std::cout << "# Testing " << Topology::name() << " in dimension " << Topology::dimension << " with order " << o << std::endl; typename BasisFactory::Object &basis = *BasisFactory::template create(o); ret |= test(basis,*pointsPtr,verbose); // define the macro TEST_OUTPUT_FUNCTIONS to output files containing functions and // derivatives in a human readabible form (aka LaTeX source) #ifdef TEST_OUTPUT_FUNCTIONS std::stringstream name; name << "lagrange_" << Topology::name() << "_p" << o << ".basis"; std::ofstream out(name.str().c_str()); Dune::basisPrint<0,BasisFactory,typename BasisFactory::StorageField>(out,basis); Dune::basisPrint<1,BasisFactory,typename BasisFactory::StorageField>(out,basis); #endif // TEST_OUTPUT_FUNCTIONS LagrangeCoefficientsFactory::release( pointsPtr ); BasisFactory::release( &basis ); } if (verbose) std::cout << std::endl << std::endl << std::endl; if (!ret) { std::cout << " FAILED !" << std::endl; } return ret; } int main ( int argc, char **argv ) { using namespace Dune; using namespace Impl; const unsigned int order = (argc < 2) ? 5 : atoi(argv[1]); if (argc < 2) { std::cerr << "Usage: " << argv[ 0 ] << "

" << std::endl << "Using default order of " << order << std::endl; } #ifdef TOPOLOGY return (test(order) ? 0 : 1 ); #else bool tests = true; tests &= test > (order); tests &= test > (order); tests &= test > > (order); tests &= test > >(order); tests &= test > > >(order); tests &= test > > >(order); tests &= test > > >(order); // tests &= test > > >(order); std::cout << "NOT CHECKING PYRAMID!" << std::endl; tests &= test > > > >(order); tests &= test > > > >(order); return (tests ? 0 : 1); #endif // TOPOLOGY } dune-localfunctions-2.5.1/dune/localfunctions/test/test-localfe.cc000066400000000000000000000243321313314431100253170ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "../lagrange/p0.hh" #include "../lagrange/p1.hh" #include "../lagrange/prismp1.hh" #include "../lagrange/prismp2.hh" #include "../lagrange/pyramidp1.hh" #include "../lagrange/pyramidp2.hh" #include "../lagrange/q1.hh" #include "../lagrange/p23d.hh" #include "../lagrange/pq22d.hh" #include "../lagrange/pk.hh" #include "../lagrange/qk.hh" #include "../brezzidouglasmarini/brezzidouglasmarini1cube2d.hh" #include "../brezzidouglasmarini/brezzidouglasmarini1cube3d.hh" #include "../brezzidouglasmarini/brezzidouglasmarini2cube2d.hh" #include "../brezzidouglasmarini/brezzidouglasmarini1simplex2d.hh" #include "../brezzidouglasmarini/brezzidouglasmarini2simplex2d.hh" #include #include "../refined/refinedp1.hh" #include "../refined/refinedp0.hh" #include "../hierarchical/hierarchicalp2.hh" #include "../hierarchical/hierarchicalp2withelementbubble.hh" #include "../hierarchical/hierarchicalprismp2.hh" #include "../rannacherturek/rannacherturek.hh" #include "../raviartthomas/raviartthomassimplex.hh" #include "../raviartthomas/raviartthomascube.hh" #include "../monomial.hh" #include "../common/virtualinterface.hh" #include "../common/virtualwrappers.hh" #include "test-localfe.hh" // tmp for testing arbitrary order finite elements template struct PkLocalFiniteElementTest { static bool test() { bool success = true; Dune::PkLocalFiniteElement pklfem; TEST_FE(pklfem); return PkLocalFiniteElementTest::test() and success; } }; template struct PkLocalFiniteElementTest { static bool test() { return true; } }; template bool testMonomials() { bool success = true; Dune::GeometryType gt; gt.makeLine(); Dune::MonomialLocalFiniteElement monom1d(gt); TEST_FE(monom1d); gt.makeTriangle(); Dune::MonomialLocalFiniteElement monom2d(gt); TEST_FE(monom2d); gt.makeTetrahedron(); Dune::MonomialLocalFiniteElement monom3d(gt); TEST_FE(monom3d); return testMonomials() and success; } template<> bool testMonomials<-1>() { return true; } int main(int argc, char** argv) try { bool success = true; Dune::P0LocalFiniteElement p0lfem( Dune::GeometryType(Dune::GeometryType::simplex, 2)); TEST_FE(p0lfem); Dune::P1LocalFiniteElement p11dlfem; TEST_FE(p11dlfem); Dune::P1LocalFiniteElement p12dlfem; TEST_FE(p12dlfem); Dune::P1LocalFiniteElement p13dlfem; TEST_FE(p13dlfem); Dune::Q1LocalFiniteElement q11dlfem; TEST_FE(q11dlfem); Dune::Q1LocalFiniteElement q12dlfem; TEST_FE(q12dlfem); Dune::Q1LocalFiniteElement q13dlfem; TEST_FE(q13dlfem); Dune::PQ22DLocalFiniteElement pq22dlfem( Dune::GeometryType( Dune::GeometryType::simplex,2) ); TEST_FE(pq22dlfem); Dune::RefinedP1LocalFiniteElement refp11dlfem; TEST_FE(refp11dlfem); Dune::RefinedP1LocalFiniteElement refp12dlfem; TEST_FE(refp12dlfem); Dune::RefinedP1LocalFiniteElement refp13dlfem; TEST_FE(refp13dlfem); Dune::RefinedP0LocalFiniteElement refp01dlfem; TEST_FE(refp01dlfem); Dune::RefinedP0LocalFiniteElement refp02dlfem; TEST_FE(refp02dlfem); Dune::P23DLocalFiniteElement p23dlfem; TEST_FE(p23dlfem); // -------------------------------------------------------- // Test Brezzi-Douglas-Marini finite elements // -------------------------------------------------------- Dune::BDM1Cube2DLocalFiniteElement bdm1cube2dlfem(1); TEST_FE(bdm1cube2dlfem); Dune::BDM1Cube3DLocalFiniteElement bdm1cube3dlfem(1); TEST_FE2(bdm1cube3dlfem, DisableLocalInterpolation); Dune::BDM2Cube2DLocalFiniteElement bdm2cube2dlfem(1); TEST_FE(bdm2cube2dlfem); Dune::BDM1Simplex2DLocalFiniteElement bdm1simplex2dlfem(1); TEST_FE(bdm1simplex2dlfem); Dune::BDM2Simplex2DLocalFiniteElement bdm2simplex2dlfem(1); TEST_FE(bdm2simplex2dlfem); // -------------------------------------------------------- // Test hierarchical P2 finite elements // -------------------------------------------------------- Dune::HierarchicalP2LocalFiniteElement hierarchicalp21dlfem; TEST_FE(hierarchicalp21dlfem); Dune::HierarchicalP2LocalFiniteElement hierarchicalp22dlfem; TEST_FE(hierarchicalp22dlfem); Dune::HierarchicalP2LocalFiniteElement hierarchicalp23dlfem; TEST_FE(hierarchicalp23dlfem); Dune::HierarchicalPrismP2LocalFiniteElement hierarchicalprismp2lfem; TEST_FE(hierarchicalprismp2lfem); Dune::HierarchicalP2WithElementBubbleLocalFiniteElement hierarchicalp2bubble2dlfem; TEST_FE(hierarchicalp2bubble2dlfem); Dune::PrismP1LocalFiniteElement prismp1fem; TEST_FE(prismp1fem); Dune::PrismP2LocalFiniteElement prismp2fem; TEST_FE(prismp2fem); Dune::PyramidP1LocalFiniteElement pyramidp1fem; TEST_FE2(pyramidp1fem, DisableJacobian); Dune::PyramidP2LocalFiniteElement pyramidp2fem; TEST_FE2(pyramidp2fem, DisableJacobian); success = PkLocalFiniteElementTest<1, 1>::test() and success; success = PkLocalFiniteElementTest<1, 2>::test() and success; success = PkLocalFiniteElementTest<2, 10>::test() and success; success = PkLocalFiniteElementTest<3, 10>::test() and success; // -------------------------------------------------------- // Test some instantiations of QkLocalFiniteElement // -------------------------------------------------------- Dune::QkLocalFiniteElement qk11dlfem; TEST_FE(qk11dlfem); Dune::QkLocalFiniteElement qk02dlfem; TEST_FE(qk02dlfem); Dune::QkLocalFiniteElement qk12dlfem; TEST_FE(qk12dlfem); Dune::QkLocalFiniteElement qk22dlfem; TEST_FE(qk22dlfem); Dune::QkLocalFiniteElement qk32dlfem; TEST_FE(qk32dlfem); Dune::QkLocalFiniteElement qk03dlfem; TEST_FE(qk03dlfem); Dune::QkLocalFiniteElement qk13dlfem; TEST_FE(qk13dlfem); Dune::QkLocalFiniteElement qk23dlfem; TEST_FE(qk23dlfem); Dune::QkLocalFiniteElement qk33dlfem; TEST_FE(qk33dlfem); // -------------------------------------------------------- // Test dual mortar elements // -------------------------------------------------------- Dune::DualP1LocalFiniteElement dualp11dlfem; TEST_FE(dualp11dlfem); Dune::DualP1LocalFiniteElement dualp12dlfem; TEST_FE(dualp12dlfem); Dune::DualP1LocalFiniteElement dualp13dlfem; TEST_FE(dualp13dlfem); Dune::DualQ1LocalFiniteElement dualq11dlfem; TEST_FE(dualq11dlfem); Dune::DualQ1LocalFiniteElement dualq12dlfem; TEST_FE(dualq12dlfem); Dune::DualQ1LocalFiniteElement dualq13dlfem; TEST_FE(dualq13dlfem); // -------------------------------------------------------- // Test Raviart-Thomas Finite elements // -------------------------------------------------------- Dune::RaviartThomasSimplexLocalFiniteElement<2,double,double> rt0simplex2dlfem(Dune::GeometryType(Dune::GeometryType::simplex,2),0); TEST_FE(rt0simplex2dlfem); Dune::RaviartThomasSimplexLocalFiniteElement<2,double,double> rt1simplex2dlfem(Dune::GeometryType(Dune::GeometryType::simplex,2),1); TEST_FE(rt1simplex2dlfem); Dune::RaviartThomasCubeLocalFiniteElement rt0cube2dlfem(1); TEST_FE(rt0cube2dlfem); Dune::RaviartThomasCubeLocalFiniteElement rt0cube3dlfem(1); TEST_FE(rt0cube3dlfem); Dune::RaviartThomasCubeLocalFiniteElement rt1cube2dlfem(1); TEST_FE(rt1cube2dlfem); Dune::RaviartThomasCubeLocalFiniteElement rt1cube3dlfem(1); TEST_FE(rt1cube3dlfem); Dune::RaviartThomasCubeLocalFiniteElement rt2cube2dlfem(1); TEST_FE(rt2cube2dlfem); Dune::RaviartThomasCubeLocalFiniteElement rt3cube2dlfem(1); TEST_FE(rt3cube2dlfem); Dune::RaviartThomasCubeLocalFiniteElement rt4cube2dlfem(1); TEST_FE(rt4cube2dlfem); // -------------------------------------------------------- // Test Rannacher-Turek Finite elements // -------------------------------------------------------- Dune::RannacherTurekLocalFiniteElement rannacher_turek2dfem; TEST_FE(rannacher_turek2dfem); Dune::RannacherTurekLocalFiniteElement rannacher_turek3dfem; TEST_FE(rannacher_turek3dfem); std::cout << "Monomials are only tested up to order 2 due to the instability of interpolate()." << std::endl; success = testMonomials<2>() and success; // test virtualized FEs // notice that testFE add another level of virtualization Dune::LocalFiniteElementVirtualImp< Dune::P1LocalFiniteElement > p12dlfemVirtual(p12dlfem); TEST_FE(p12dlfemVirtual); Dune::LocalFiniteElementVirtualImp< Dune::PQ22DLocalFiniteElement > pq22dlfemVirtual(pq22dlfem); TEST_FE(pq22dlfemVirtual); Dune::LocalFiniteElementVirtualImp< Dune::LocalFiniteElementVirtualImp< Dune::P1LocalFiniteElement > > p12dlfemVirtualVirtual(p12dlfemVirtual); TEST_FE(p12dlfemVirtualVirtual); Dune::LocalFiniteElementVirtualImp< Dune::LocalFiniteElementVirtualImp< Dune::PQ22DLocalFiniteElement > > pq22dlfemVirtualVirtual(pq22dlfemVirtual); TEST_FE(pq22dlfemVirtualVirtual); typedef Dune::LocalFiniteElementVirtualInterface< Dune::P1LocalFiniteElement::Traits::LocalBasisType::Traits > Interface; TEST_FE(static_cast(p12dlfemVirtual)); return success ? 0 : 1; } catch (Dune::Exception e) { std::cout << e << std::endl; return 1; } dune-localfunctions-2.5.1/dune/localfunctions/test/test-localfe.hh000066400000000000000000000740601313314431100253340ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH #define DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH /** \file \brief Unit tests for LocalFiniteElement objects * * \note This header is not part of the official Dune API and might be subject * to change. You can use this header to test external finite element * implementations, but be warned that your tests might break with future * Dune versions. */ #include #include #include #include #include #include #include #include #include double TOL = 1e-9; // The FD approximation used for checking the Jacobian uses half of the // precision -- so we have to be a little bit more tolerant here. double jacobianTOL = 1e-5; // sqrt(TOL) template class Func : // public Dune::LocalFiniteElementFunctionBase::type public Dune::LocalFiniteElementFunctionBase::FunctionBase // public Dune::LocalFiniteElementFunctionBase::VirtualFunctionBase { public: typedef typename FE::Traits::LocalBasisType::Traits::DomainType DomainType; typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType; typedef typename Dune::Function Base; void evaluate (const DomainType& x, RangeType& y) const { y = 0; DomainType c(0.5); c -= x; y[0] = exp(-3.0*c.two_norm2()); } }; // This class defines a local finite element function. // It is determined by a local finite element and // representing the local basis and a coefficient vector. // This provides the evaluate method needed by the interpolate() // method. template class LocalFEFunction : // public Dune::LocalFiniteElementFunctionBase::type public Dune::LocalFiniteElementFunctionBase::FunctionBase // public Dune::LocalFiniteElementFunctionBase::VirtualFunctionBase { public: typedef typename FE::Traits::LocalBasisType::Traits::DomainType DomainType; typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType; typedef typename Dune::Function Base; typedef typename FE::Traits::LocalBasisType::Traits::RangeFieldType CT; LocalFEFunction(const FE& fe) : fe_(fe) { resetCoefficients(); } void resetCoefficients() { coeff_.resize(fe_.localBasis().size()); for(std::size_t i=0; i yy; fe_.localBasis().evaluateFunction(x, yy); y = 0.0; for (std::size_t i=0; i coeff_; private: const FE& fe_; }; // Check if localInterpolation is consistens with // localBasis evaluation. template bool testLocalInterpolation(const FE& fe, int n=5) { bool success = true; LocalFEFunction f(fe); std::vector::CT> coeff; for(int i=0; i TOL*((std::abs(f.coeff_[j])>1) ? std::abs(f.coeff_[j]) : 1.) ) { std::cout << std::setprecision(16); std::cout << "Bug in LocalInterpolation for finite element type " << Dune::className(fe) << std::endl; std::cout << " Interpolation weight " << j << " differs by " << std::abs(coeff[j]-f.coeff_[j]) << " from coefficient of linear combination." << std::endl; std::cout << std::endl; success = false; } } } return success; } // check whether Jacobian agrees with FD approximation template bool testJacobian(const FE& fe, unsigned order = 2) { typedef typename FE::Traits::LocalBasisType LB; bool success = true; // //////////////////////////////////////////////////////////// // Check the partial derivatives by comparing them // to finite difference approximations // //////////////////////////////////////////////////////////// // A set of test points const Dune::QuadratureRule quad = Dune::QuadratureRules::rule(fe.type(),order); // Loop over all quadrature points for (size_t i=0; i& testPoint = quad[i].position(); // Get the shape function derivatives there std::vector jacobians; fe.localBasis().evaluateJacobian(testPoint, jacobians); if(jacobians.size() != fe.localBasis().size()) { std::cout << "Bug in evaluateJacobianGlobal() for finite element type " << Dune::className(fe) << std::endl; std::cout << " Jacobian vector has size " << jacobians.size() << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } // Loop over all shape functions in this set for (unsigned int j=0; j upPos = testPoint; Dune::FieldVector downPos = testPoint; upPos[k] += jacobianTOL; downPos[k] -= jacobianTOL; std::vector upValues, downValues; fe.localBasis().evaluateFunction(upPos, upValues); fe.localBasis().evaluateFunction(downPos, downValues); //Loop over all components for(int l=0; l < LB::Traits::dimRange; ++l) { // The current partial derivative, just for ease of notation double derivative = jacobians[j][l][k]; double finiteDiff = (upValues[j][l] - downValues[j][l]) / (2*jacobianTOL); // Check if ( std::abs(derivative-finiteDiff) > TOL/jacobianTOL*((std::abs(finiteDiff)>1) ? std::abs(finiteDiff) : 1.) ) { std::cout << std::setprecision(16); std::cout << "Bug in evaluateJacobian() for finite element type " << Dune::className(fe) << std::endl; std::cout << " Shape function derivative does not agree with " << "FD approximation" << std::endl; std::cout << " Shape function " << j << " component " << l << " at position " << testPoint << ": derivative in " << "direction " << k << " is " << derivative << ", but " << finiteDiff << " is expected." << std::endl; std::cout << std::endl; success = false; } } //Loop over all components } // Loop over all directions } // Loop over all shape functions in this set } // Loop over all quadrature points return success; } /** \brief Helper class to test the 'evaluate' method * * It implements a static loop over the available diff orders */ template struct TestEvaluate { template static bool test(const FE& fe, double eps, double delta, std::size_t order = 2) { std::cout << "No test for differentiability order " << diffOrder << std::endl; return TestEvaluate::test(fe, eps, delta, order); } }; /** \brief Specialization to test the 'evaluate' method for zero-order partial derivatives, i.e., values */ template<> struct TestEvaluate<0> { template static bool test(const FE& fe, double eps, double delta, std::size_t order = 2) { typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType; constexpr auto dimDomain = FE::Traits::LocalBasisType::Traits::dimDomain; bool success = true; ////////////////////////////////////////////////////////////// // Check the partial derivatives by comparing them // to finite difference approximations ////////////////////////////////////////////////////////////// // A set of test points const auto& quad = Dune::QuadratureRules::rule(fe.type(), order); // Loop over all quadrature points for (size_t i = 0; i < quad.size(); i++) { // Get a test point const Dune::FieldVector& testPoint = quad[i].position(); // Get the shape function values there using the 'partial' method std::vector partialValues; std::array multiIndex; std::fill(multiIndex.begin(), multiIndex.end(), 0); fe.localBasis().partial(multiIndex, testPoint, partialValues); if (partialValues.size() != fe.localBasis().size()) { std::cout << "Bug in partial() for finite element type " << Dune::className(fe) << std::endl; std::cout << " values vector has size " << partialValues.size() << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } // Get reference values std::vector referenceValues; fe.localBasis().evaluateFunction(testPoint, referenceValues); // Loop over all shape functions in this set for (unsigned int j = 0; j < fe.localBasis().size(); ++j) { // Loop over all components for (int l = 0; l < FE::Traits::LocalBasisType::Traits::dimRange; ++l) { // Check the 'partial' method if (std::abs(partialValues[j][l] - referenceValues[j][l]) > TOL / jacobianTOL * ((std::abs(referenceValues[j][l]) > 1) ? std::abs(referenceValues[j][l]) : 1.)) { std::cout << std::setprecision(16); std::cout << "Bug in partial() for finite element type " << Dune::className(fe) << std::endl; std::cout << " Shape function value does not agree with " << "output of method evaluateFunction." << std::endl; std::cout << " Shape function " << j << " component " << l << " at position " << testPoint << ": value is " << partialValues[j][l] << ", but " << referenceValues[j][l] << " is expected." << std::endl; std::cout << std::endl; success = false; } } //Loop over all components } // Loop over all shape functions in this set } // Loop over all quadrature points return success; } }; /** \brief Specialization to test the 'evaluate' method for first-order partial derivatives */ template<> struct TestEvaluate<1> { template static bool test(const FE& fe, double eps, double delta, std::size_t order = 2) { typedef typename FE::Traits::LocalBasisType LB; typedef typename LB::Traits::RangeFieldType RangeField; bool success = true; ////////////////////////////////////////////////////////////// // Check the partial derivatives by comparing them // to finite difference approximations ////////////////////////////////////////////////////////////// // A set of test points const Dune::QuadratureRule quad = Dune::QuadratureRules::rule(fe.type(), order); // Loop over all quadrature points for (size_t i = 0; i < quad.size(); i++) { // Get a test point const Dune::FieldVector& testPoint = quad[i].position(); // Loop over all directions for (int k = 0; k < LB::Traits::dimDomain; k++) { std::array direction = {{k}}; // Get the shape function derivatives there using the 'evaluate' method std::vector firstDerivatives; DUNE_NO_DEPRECATED_BEGIN fe.localBasis().template evaluate<1>(direction, testPoint, firstDerivatives); DUNE_NO_DEPRECATED_END if (firstDerivatives.size() != fe.localBasis().size()) { std::cout << "Bug in evaluate() for finite element type " << Dune::className(fe) << std::endl; std::cout << " firstDerivatives vector has size " << firstDerivatives.size() << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } // Get the shape function derivatives there using the 'partial' method std::vector firstPartialDerivatives; std::array multiIndex; std::fill(multiIndex.begin(), multiIndex.end(), 0); multiIndex[k]++; fe.localBasis().partial(multiIndex, testPoint, firstPartialDerivatives); if (firstPartialDerivatives.size() != fe.localBasis().size()) { std::cout << "Bug in evaluate() for finite element type " << Dune::className(fe) << std::endl; std::cout << " firstDerivatives vector has size " << firstDerivatives.size() << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } // Loop over all shape functions in this set for (unsigned int j = 0; j < fe.localBasis().size(); ++j) { // Compute an approximation to the derivative by finite differences Dune::FieldVector upPos = testPoint; Dune::FieldVector downPos = testPoint; upPos[k] += jacobianTOL; downPos[k] -= jacobianTOL; std::vector upValues, downValues; fe.localBasis().evaluateFunction(upPos, upValues); fe.localBasis().evaluateFunction(downPos, downValues); // Loop over all components for (int l = 0; l < LB::Traits::dimRange; ++l) { // The current partial derivative, just for ease of notation RangeField derivative = firstDerivatives[j][l]; RangeField finiteDiff = (upValues[j][l] - downValues[j][l]) / (2 * jacobianTOL); // Check the 'evaluate' method if (std::abs(derivative - finiteDiff) > TOL / jacobianTOL * ((std::abs(finiteDiff) > 1) ? std::abs(finiteDiff) : 1.)) { std::cout << std::setprecision(16); std::cout << "Bug in evaluate<1>() for finite element type " << Dune::className(fe) << std::endl; std::cout << " Shape function derivative does not agree with " << "FD approximation" << std::endl; std::cout << " Shape function " << j << " component " << l << " at position " << testPoint << ": derivative in " << "direction " << k << " is " << derivative << ", but " << finiteDiff << " is expected." << std::endl; std::cout << std::endl; success = false; } // Check the 'partial' method RangeField partialDerivative = firstPartialDerivatives[j][l]; if (std::abs(partialDerivative - finiteDiff) > TOL / jacobianTOL * ((std::abs(finiteDiff) > 1) ? std::abs(finiteDiff) : 1.)) { std::cout << std::setprecision(16); std::cout << "Bug in partial() for finite element type " << Dune::className(fe) << std::endl; std::cout << " Shape function derivative does not agree with " << "FD approximation" << std::endl; std::cout << " Shape function " << j << " component " << l << " at position " << testPoint << ": derivative in " << "direction " << k << " is " << derivative << ", but " << finiteDiff << " is expected." << std::endl; std::cout << std::endl; success = false; } } // Loop over all directions } //Loop over all components } // Loop over all shape functions in this set } // Loop over all quadrature points // Recursively call the zero-order test return success and TestEvaluate<0>::test(fe, eps, delta, order); } }; /** \brief Specialization to test second-order partial derivatives */ template<> struct TestEvaluate<2> { template static bool test(const FE& fe, double eps, double delta, std::size_t order = 2) { typedef typename FE::Traits::LocalBasisType LocalBasis; typedef typename LocalBasis::Traits::DomainFieldType DF; typedef typename LocalBasis::Traits::DomainType Domain; static const int dimDomain = LocalBasis::Traits::dimDomain; static const std::size_t dimR = LocalBasis::Traits::dimRange; typedef typename LocalBasis::Traits::RangeType Range; typedef typename LocalBasis::Traits::RangeFieldType RangeField; bool success = true; ////////////////////////////////////////////////////////////// // Check the partial derivatives by comparing them // to finite difference approximations ////////////////////////////////////////////////////////////// // A set of test points const Dune::QuadratureRule quad = Dune::QuadratureRules::rule(fe.type(), order); // Loop over all quadrature points for (std::size_t i = 0; i < quad.size(); i++) { // Get a test point const Domain& testPoint = quad[i].position(); // For testing the 'evaluate' method std::array >, dimR> hessians; for (size_t k = 0; k < dimR; k++) hessians[k].resize(fe.size()); // For testing the 'partial' method std::array >, dimR> partialHessians; for (size_t k = 0; k < dimR; k++) partialHessians[k].resize(fe.size()); //loop over all local directions for (int dir0 = 0; dir0 < dimDomain; dir0++) { for (int dir1 = 0; dir1 < dimDomain; dir1++) { std::array directions = {{ dir0, dir1 }}; // Get the shape function derivatives there using the 'evaluate' method std::vector secondDerivative; DUNE_NO_DEPRECATED_BEGIN fe.localBasis().template evaluate<2>(directions, testPoint, secondDerivative); DUNE_NO_DEPRECATED_END if (secondDerivative.size() != fe.localBasis().size()) { std::cout << "Bug in evaluate<2>() for finite element type " << Dune::className() << ":" << std::endl; std::cout << " return vector has size " << secondDerivative.size() << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } //combine to Hesse matrices for (size_t k = 0; k < dimR; k++) for (std::size_t j = 0; j < fe.localBasis().size(); ++j) hessians[k][j][dir0][dir1] = secondDerivative[j][k]; // Get the shape function derivatives there using the 'partial' method std::vector secondPartialDerivative; std::array multiIndex; std::fill(multiIndex.begin(), multiIndex.end(), 0); multiIndex[dir0]++; multiIndex[dir1]++; fe.localBasis().partial(multiIndex, testPoint, secondPartialDerivative); if (secondPartialDerivative.size() != fe.localBasis().size()) { std::cout << "Bug in partial() for finite element type " << Dune::className() << ":" << std::endl; std::cout << " return vector has size " << secondPartialDerivative.size() << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } //combine to Hesse matrices for (size_t k = 0; k < dimR; k++) for (std::size_t j = 0; j < fe.localBasis().size(); ++j) partialHessians[k][j][dir0][dir1] = secondPartialDerivative[j][k]; } } //loop over all directions // Loop over all shape functions in this set for (std::size_t j = 0; j < fe.localBasis().size(); ++j) { // Loop over all local directions for (std::size_t dir0 = 0; dir0 < dimDomain; ++dir0) { for (unsigned int dir1 = 0; dir1 < dimDomain; dir1++) { // Compute an approximation to the derivative by finite differences std::array neighbourPos; std::fill(neighbourPos.begin(), neighbourPos.end(), testPoint); neighbourPos[0][dir0] += delta; neighbourPos[0][dir1] += delta; neighbourPos[1][dir0] -= delta; neighbourPos[1][dir1] += delta; neighbourPos[2][dir0] += delta; neighbourPos[2][dir1] -= delta; neighbourPos[3][dir0] -= delta; neighbourPos[3][dir1] -= delta; std::array, 4> neighbourValues; for (int k = 0; k < 4; k++) fe.localBasis().evaluateFunction(neighbourPos[k], neighbourValues[k]); //Loop over all components for (std::size_t k = 0; k < dimR; ++k) { // The current partial derivative, just for ease of notation, evaluated by the 'evaluate' method RangeField derivative = hessians[k][j][dir0][dir1]; RangeField finiteDiff = (neighbourValues[0][j][k] - neighbourValues[1][j][k] - neighbourValues[2][j][k] + neighbourValues[3][j][k]) / (4 * delta * delta); // Check if (std::abs(derivative - finiteDiff) > eps / delta * (std::max(std::abs(finiteDiff), 1.0))) { std::cout << std::setprecision(16); std::cout << "Bug in evaluate<2>() for finite element type " << Dune::className() << ":" << std::endl; std::cout << " Second shape function derivative does not agree with " << "FD approximation" << std::endl; std::cout << " Shape function " << j << " component " << k << " at position " << testPoint << ": derivative in " << "local direction (" << dir0 << ", " << dir1 << ") is " << derivative << ", but " << finiteDiff << " is expected." << std::endl; std::cout << std::endl; success = false; } // The current partial derivative, just for ease of notation, evaluated by the 'partial' method RangeField partialDerivative = partialHessians[k][j][dir0][dir1]; // Check if (std::abs(partialDerivative - finiteDiff) > eps / delta * (std::max(std::abs(finiteDiff), 1.0))) { std::cout << std::setprecision(16); std::cout << "Bug in partial() for finite element type " << Dune::className() << ":" << std::endl; std::cout << " Second shape function derivative does not agree with " << "FD approximation" << std::endl; std::cout << " Shape function " << j << " component " << k << " at position " << testPoint << ": derivative in " << "local direction (" << dir0 << ", " << dir1 << ") is " << partialDerivative << ", but " << finiteDiff << " is expected." << std::endl; std::cout << std::endl; success = false; } } //Loop over all components } } // Loop over all local directions } // Loop over all shape functions in this set } // Loop over all quadrature points // Recursively call the first-order test return success and TestEvaluate<1>::test(fe, eps, delta, order); } }; template<> struct TestEvaluate<-1> { template static bool test(const FE& fe, double eps, double delta, std::size_t order = 2) { return true; } }; // Flags for disabling parts of testFE enum { DisableNone = 0, DisableLocalInterpolation = 1, DisableVirtualInterface = 2, DisableJacobian = 4, DisableEvaluate = 8 }; // call tests for given finite element template bool testFE(const FE& fe, char disabledTests = DisableNone, unsigned order = 2) { std::vector c; bool success = true; if (FE::Traits::LocalBasisType::Traits::dimDomain != fe.type().dim()) { std::cout << "Bug in type() for finite element type " << Dune::className(fe) << std::endl; std::cout << " Coordinate dimension is " << FE::Traits::LocalBasisType::Traits::dimDomain << std::endl; std::cout << " but GeometryType is " << fe.type() << " with dimension " << fe.type().dim() << std::endl; success = false; } if (fe.size() != fe.localBasis().size()) { std::cout << "Bug in finite element type " << Dune::className(fe) << std::endl; std::cout << " Size reported by LocalFiniteElement is " << fe.size() << std::endl; std::cout << " but size reported by LocalBasis is " << fe.localBasis().size() << std::endl; success = false; } // Make sure evaluateFunction returns the correct number of values std::vector values; fe.localBasis().evaluateFunction(Dune::ReferenceElements::general(fe.type()).position(0,0), values); if (values.size() != fe.size()) { std::cout << "Bug in finite element type " << Dune::className(fe) << std::endl; std::cout << " LocalFiniteElement.size() returns " << fe.size() << "," << std::endl; std::cout << " but LocalBasis::evaluateFunction returns " << values.size() << " values!" << std::endl; success = false; } if (fe.size() != fe.localCoefficients().size()) { std::cout << "Bug in finite element type " << Dune::className(fe) << std::endl; std::cout << " Size reported by LocalFiniteElement is " << fe.size() << std::endl; std::cout << " but size reported by LocalCoefficients is " << fe.localCoefficients().size() << std::endl; success = false; } if (not (disabledTests & DisableLocalInterpolation)) { fe.localInterpolation().interpolate(Func(),c); success = testLocalInterpolation(fe) and success; } if (not (disabledTests & DisableJacobian)) { success = testJacobian(fe, order) and success; } else { // make sure diffOrder is 0 success = (FE::Traits::LocalBasisType::Traits::diffOrder == 0) and success; } if (not (disabledTests & DisableEvaluate)) { success = TestEvaluate::test(fe, TOL, jacobianTOL, order) and success; } if (not (disabledTests & DisableVirtualInterface)) { typedef typename FE::Traits::LocalBasisType::Traits LBTraits; typedef typename Dune::FixedOrderLocalBasisTraits::Traits C0LBTraits; typedef typename Dune::LocalFiniteElementVirtualInterface VirtualFEInterface; typedef typename Dune::LocalFiniteElementVirtualImp VirtualFEImp; const VirtualFEImp virtualFE(fe); if (not (disabledTests & DisableLocalInterpolation)) success = testLocalInterpolation(virtualFE) and success; if (not (disabledTests & DisableJacobian)) { success = testJacobian(virtualFE) and success; } else { // make sure diffOrder is 0 success = (VirtualFEInterface::Traits::LocalBasisType::Traits::diffOrder == 0) and success; } } return success; } #define TEST_FE(A) { bool b = testFE(A); std::cout << "testFE(" #A ") " << (b?"succeeded\n":"failed\n"); success &= b; } #define TEST_FE2(A,B) { bool b = testFE(A, B); if (!b) std::cerr << "testFE(" #A ", " #B ") " << (b?"succeeded\n":"failed\n"); success &= b; } #endif // DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH dune-localfunctions-2.5.1/dune/localfunctions/test/test-monomial.cc000066400000000000000000000034711313314431100255260ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "geometries.hh" #include "test-fe.hh" // tolerance for floating-point comparisons const double eps = 1e-9; // stepsize for numerical differentiation const double delta = 1e-5; template static void Order(int &result) { std::cout << "== Checking global-valued monomial elements (with " << "dim=" << dim << ", p=" << p << ")" << std::endl; typedef TestGeometries TestGeos; static const TestGeos testGeos; typedef typename TestGeos::Geometry Geometry; Dune::MonomialFiniteElementFactory feFactory; for(std::size_t i = 0; i < testGeos.size(); ++i) { const Geometry &geo = testGeos[i]; std::cout << "=== GeometryType " << geo.type() << std::endl; bool success = testFE(geo, feFactory.make(geo), eps, delta); if(success && result != 1) result = 0; else result = 1; } } template static void Dim(int &result) { Dune::Hybrid::forEach(Dune::Std::make_index_sequence<4>{},[&](auto i){Order(result);}); } int main(int argc, char** argv) { try { int result = 77; Dune::Hybrid::forEach(Dune::Std::make_index_sequence<3>{},[&](auto i){Dim(result);}); return result; } catch (const Dune::Exception& e) { std::cerr << e << std::endl; throw; } } dune-localfunctions-2.5.1/dune/localfunctions/test/test-orthonormal.cc000066400000000000000000000105261313314431100262560ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include #include #include /** * \file * \brief Performs some tests for the generic orthonormal * shape functions on simplices. * * The topology can be chosen at compile time by setting TOPOLOGY * to a string like * \code * Pyramid > > * \endcode * which generates a 2d simplex. If TOPOLOGY is not set, all * topologies up to 4d are tested. Note, this may lead to prolonged * compiler runs. * * For debugging purpuse the functions and the derivatives can be * printed. You have to define the macro TEST_OUTPUT_FUNCTIONS to * activate this function. */ #if HAVE_GMP typedef Dune::GMPField< 128 > StorageField; typedef Dune::GMPField< 512 > ComputeField; #else typedef double StorageField; typedef double ComputeField; #endif template bool test(unsigned int order) { bool ret = true; Dune::GeometryType gt(Topology::id, Topology::dimension); for (unsigned int o = 0; o <= order; ++o) { std::cout << "Testing " << Topology::name() << " in dimension " << Topology::dimension << " with order " << o << std::endl; typedef Dune::OrthonormalBasisFactory BasisFactory; const typename BasisFactory::Object &basis = *BasisFactory::template create(o); const unsigned int size = basis.size( ); std::vector< Dune::FieldVector< double, 1 > > y( size ); std::vector< Dune::FieldVector< double, 1 > > m( size * size ); for( unsigned int i = 0; i < size * size; ++i ) m[ i ] = 0; const Dune::QuadratureRule &quadrature = Dune::QuadratureRules::rule(gt,2*order+1); const unsigned int quadratureSize = quadrature.size(); for( unsigned int qi = 0; qi < quadratureSize; ++qi ) { basis.evaluate( quadrature[qi].position(), y ); for( unsigned int i = 0; i < size; ++i ) { for( unsigned int j = 0; j < size; ++j ) m[ i*size + j ] += quadrature[qi].weight() * y[ i ] * y[ j ]; } } for( unsigned int i = 0; i < size; ++i ) { for( unsigned int j = 0; j < size; ++j ) { const double value = m[ i*size + j ]; if( std::abs( value - double( i == j ) ) > 1200.*Dune::Zero::epsilon() ) { std::cout << "i = " << i << ", j = " << j << ": " << std::abs( value - double( i == j ) ) << std::endl; ret = false; } } } // define the macro TEST_OUTPUT_FUNCTIONS to output files containing functions and // derivatives in a human readabible form (aka LaTeX source) #ifdef TEST_OUTPUT_FUNCTIONS std::stringstream name; name << "orthonormal_" << Topology::name() << "_p" << o << ".basis"; std::ofstream out(name.str().c_str()); Dune::basisPrint<0,BasisFactory,typename BasisFactory::StorageField>(out,basis); Dune::basisPrint<1,BasisFactory,typename BasisFactory::StorageField>(out,basis); #endif // TEST_OUTPUT_FUNCTIONS BasisFactory::release(&basis); } if (!ret) { std::cout << " FAILED !" << std::endl; } std::cout << std::endl; return ret; } int main ( int argc, char **argv ) { using namespace Dune; using namespace Impl; const unsigned int order = (argc < 2) ? 5 : atoi(argv[1]); if (argc < 2) { std::cerr << "Usage: " << argv[ 0 ] << "

" << std::endl << "Using default order of " << order << std::endl; } #ifdef TOPOLOGY return (test(order) ? 0 : 1 ); #else bool tests = true; tests &= test > (order); tests &= test > (order); tests &= test > > (order); tests &= test > >(order); tests &= test > > >(order); tests &= test > > >(order); tests &= test > > >(order); tests &= test > > >(order); tests &= test > > > >(order); tests &= test > > > >(order); return (tests ? 0 : 1); #endif // TOPOLOGY } dune-localfunctions-2.5.1/dune/localfunctions/test/test-pk2d.cc000066400000000000000000000033011313314431100245430ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "geometries.hh" #include "test-fe.hh" // tolerance for floating-point comparisons static const double eps = 1e-9; // stepsize for numerical differentiation static const double delta = 1e-5; template static void test(int &result) { std::cout << "== Checking global-valued Pk2D elements (with k=" << k << ")" << std::endl; Dune::GeometryType gt; gt.makeTriangle(); typedef TestGeometries TestGeos; static const TestGeos testGeos; typedef TestGeos::Geometry Geometry; const Geometry &geo = testGeos.get(gt); std::size_t vertexIds[] = {0, 1, 2}; Dune::GeneralVertexOrder<2, std::size_t> vo(gt, vertexIds+0, vertexIds+3); Dune::Pk2DFiniteElementFactory feFactory; bool success = testFE(geo, feFactory.make(geo, vo), eps, delta); if(success && result != 1) result = 0; else result = 1; } int main(int argc, char** argv) { try { int result = 77; static constexpr std::size_t max_k = 20; Dune::Hybrid::forEach(Dune::Std::make_index_sequence{},[&](auto i){test(result);}); return result; } catch (const Dune::Exception& e) { std::cerr << e << std::endl; throw; } } dune-localfunctions-2.5.1/dune/localfunctions/test/test-power-monomial.cc000066400000000000000000000046531313314431100266630ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "geometries.hh" #include "test-fe.hh" // tolerance for floating-point comparisons // be a little bit more lenient here than usual, the momom local basis // is known to become more and more unstable with increasing order static const double eps = 1e-8; // stepsize for numerical differentiation static const double delta = 1e-5; template static void Order(int &result) { std::cout << "== Checking global-valued Power elements (with " << "dimR=" << dimR << ") wrapping Monom elements (with " << "dimD=" << dimD << ", p=" << p << ")" << std::endl; typedef TestGeometries TestGeos; static const TestGeos testGeos; typedef typename TestGeos::Geometry Geometry; typedef Dune::MonomialFiniteElementFactory BackendFEFactory; BackendFEFactory backendFEFactory; typedef typename BackendFEFactory::FiniteElement BackendFE; Dune::PowerFiniteElementFactory feFactory; for(std::size_t i = 0; i < testGeos.size(); ++i) { const Geometry &geo = testGeos[i]; std::cout << "=== GeometryType " << geo.type() << std::endl; bool success = testFE(geo, feFactory.make(backendFEFactory.make(geo)), eps, delta); if(success && result != 1) result = 0; else result = 1; } } template static void DimR(int &result) { Dune::Hybrid::forEach(Dune::Std::make_index_sequence<4>{},[&](auto i){Order(result);}); } template static void DimD(int &result) { Dune::Hybrid::forEach(Dune::Std::make_index_sequence<4>{},[&](auto i){DimR(result);}); } int main(int argc, char** argv) { try { int result = 77; Dune::Hybrid::forEach(Dune::Std::make_index_sequence<3>{},[&](auto i){DimD(result);}); return result; } catch (const Dune::Exception& e) { std::cerr << e << std::endl; throw; } } dune-localfunctions-2.5.1/dune/localfunctions/test/test-q1.cc000066400000000000000000000026021313314431100242270ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "geometries.hh" #include "test-fe.hh" template void testQ1(int &result) { // tolerance for floating-point comparisons static const double eps = 1e-9; // stepsize for numerical differentiation static const double delta = 1e-5; std::cout << "== Checking global-valued Q1 elements (with dim=" << dim << ")" << std::endl; Dune::GeometryType gt; gt.makeCube(dim); typedef TestGeometries TestGeos; static const TestGeos testGeos; typedef typename TestGeos::Geometry Geometry; const Geometry &geo = testGeos.get(gt); Dune::Q1FiniteElementFactory feFactory; bool success = testFE(geo, feFactory.make(geo), eps, delta); if(success && result != 1) result = 0; else result = 1; } int main(int argc, char** argv) { try { int result = 77; testQ1<0>(result); testQ1<1>(result); testQ1<2>(result); testQ1<3>(result); return result; } catch (const Dune::Exception& e) { std::cerr << e << std::endl; throw; } } dune-localfunctions-2.5.1/dune/localfunctions/test/test-q2.cc000066400000000000000000000026311313314431100242320ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "geometries.hh" #include "test-fe.hh" template void test(const double& eps, const double& delta, int& result) { std::cout << "== Checking global-valued Q2 " << dim << "D elements" << std::endl; Dune::GeometryType gt; gt.makeCube(dim); typedef TestGeometries TestGeos; static const TestGeos testGeos; typedef typename TestGeos::Geometry Geometry; const Geometry &geo = testGeos.get(gt); Dune::Q2FiniteElementFactory feFactory; bool success = testFE(geo, feFactory.make(geo), eps, delta); if(success && result != 1) result = 0; else result = 1; } int main(int argc, char** argv) { try { // tolerance for floating-point comparisons static const double eps = 1e-9; // stepsize for numerical differentiation static const double delta = 1e-5; int result = 77; test<1>(eps, delta, result); test<2>(eps, delta, result); test<3>(eps, delta, result); return result; } catch (const Dune::Exception& e) { std::cerr << e << std::endl; throw; } } dune-localfunctions-2.5.1/dune/localfunctions/test/test-raviartthomassimplex.cc000066400000000000000000000070011313314431100301720ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include /** * \file * \brief Performs some tests for the generic Raviart-Thomas * shape functions on simplices. * * The topology can be chosen at compile time by setting TOPOLOGY * to a string like * \code * Pyramid > > * \endcode * which generates a 2d simplex. If TOPOLOGY is not set, all * topologies up to 4d are tested. Note, this may lead to prolonged * compiler runs. * * For debugging purpuse the functions and the derivatives can be * printed. You have to define the macro TEST_OUTPUT_FUNCTIONS to * activate this function. */ #if HAVE_GMP typedef Dune::GMPField< 128 > StorageField; typedef Dune::GMPField< 512 > ComputeField; #else typedef double StorageField; typedef double ComputeField; #endif template bool test(unsigned int order) { bool ret = true; for (unsigned int o = 0; o <= order; ++o) { std::cout << "Testing " << Topology::name() << " in dimension " << Topology::dimension << " with order " << o << std::endl; typedef Dune::RaviartThomasBasisFactory BasisFactory; const typename BasisFactory::Object &basis = *BasisFactory::template create(o); // define the macro TEST_OUTPUT_FUNCTIONS to output files containing functions and // derivatives in a human readabible form (aka LaTeX source) #ifdef TEST_OUTPUT_FUNCTIONS std::stringstream name; name << "rt_" << Topology::name() << "_p" << o << ".basis"; std::ofstream out(name.str().c_str()); Dune::basisPrint<0,BasisFactory,typename BasisFactory::StorageField>(out,basis); Dune::basisPrint<1,BasisFactory,typename BasisFactory::StorageField>(out,basis); #endif // TEST_OUTPUT_FUNCTIONS // test interpolation typedef Dune::RaviartThomasL2InterpolationFactory InterpolationFactory; const typename InterpolationFactory::Object &interpol = *InterpolationFactory::template create(o); Dune::LFEMatrix matrix; interpol.interpolate(basis,matrix); for (unsigned int i=0; i 1000.*Dune::Zero::epsilon() ) std::cout << " non-zero entry in interpolation matrix: " << "(" << i << "," << j << ") = " << Dune::field_cast(matrix(i,j)) << std::endl; BasisFactory::release(&basis); } if (!ret) { std::cout << " FAILED !" << std::endl; } return ret; } int main ( int argc, char **argv ) { using namespace Dune; using namespace Impl; const unsigned int order = (argc < 2) ? 5 : atoi(argv[1]); if (argc < 2) { std::cerr << "Usage: " << argv[ 0 ] << "

" << std::endl << "Using default order of " << order << std::endl; } #ifdef TOPOLOGY return (test(order) ? 0 : 1 ); #else bool tests = true; tests &= test > (order); tests &= test > >(order); tests &= test > > >(order); tests &= test > > > >(order); return (tests ? 0 : 1); #endif // TOPOLOGY } dune-localfunctions-2.5.1/dune/localfunctions/test/testgenericfem.cc000066400000000000000000000104611313314431100257370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include // Lagrange type elements #include #include // DG type elements #include // Raviart Thomas type elements #include #include "test-localfe.hh" int main(int argc, char** argv) try { bool success = true; std::cout << "Testing LagrangeLocalFiniteElement on 3d" << " simplex elements with double precision" << std::endl; for (unsigned int order=1; order<=6; ++order) { std::cout << "order : " << order << std::endl; Dune::LagrangeLocalFiniteElement lagrangeSimplex(Dune::GeometryType(Dune::GeometryType::simplex, 3), order); TEST_FE(lagrangeSimplex); } std::cout << "Testing LagrangeLocalFiniteElement on 2d" << " cube elements with double precision" << std::endl; for (unsigned int order=1; order<=4; ++order) { std::cout << "order : " << order << std::endl; Dune::LagrangeLocalFiniteElement lagrangeCube(Dune::GeometryType(Dune::GeometryType::cube, 2), order); TEST_FE(lagrangeCube); } #if HAVE_GMP std::cout << "Testing LagrangeLocalFiniteElement on 2d" << " simplex elements with higher precision" << std::endl; for (unsigned int order=5; order<=8; ++order) { std::cout << "order : " << order << std::endl; Dune::LagrangeLocalFiniteElement,Dune::GMPField<256> > lagrangeSimplex(Dune::GeometryType(Dune::GeometryType::simplex, 2), order); TEST_FE(lagrangeSimplex); } #endif std::cout << "Testing DGLagrangeLocalFiniteElement on 3d" << " cube elements with double precision" << std::endl; for (unsigned int order=1; order<=2; ++order) { std::cout << "order : " << order << std::endl; typedef Dune::LagrangeLocalFiniteElement FE; Dune::DGLocalFiniteElement dglagrangeCube(Dune::GeometryType(Dune::GeometryType::cube, 3), order); TEST_FE(dglagrangeCube); } std::cout << "Testing L2LagrangeLocalFiniteElement on 3d" << " cube elements with double precision" << std::endl; for (unsigned int order=1; order<=3; ++order) { std::cout << "order : " << order << std::endl; typedef Dune::LagrangeLocalFiniteElement FE; Dune::L2LocalFiniteElement dglagrangeCube(Dune::GeometryType(Dune::GeometryType::cube, 3), order); TEST_FE(dglagrangeCube); } #if HAVE_GMP std::cout << "Testing OrthonormalFiniteElement on 3d" << " prism elements with higher precision" << std::endl; for (unsigned int order=7; order>=4; --order) { std::cout << "order : " << order << std::endl; Dune::OrthonormalLocalFiniteElement<3,double,double, Dune::GMPField<64>,Dune::GMPField<256> > onbPrism(Dune::GeometryType(Dune::GeometryType::prism, 3), order); TEST_FE(onbPrism); } #endif std::cout << "Testing OrthonormalFiniteElement on 3d" << " prism elements with double precision" << std::endl; for (unsigned int order=4; order>=1; --order) { std::cout << "order : " << order << std::endl; Dune::OrthonormalLocalFiniteElement<3,double,double> onbPrism(Dune::GeometryType(Dune::GeometryType::prism, 3), order); TEST_FE(onbPrism); } std::cout << "Testing RaviartThomasSimplexFiniteElement on 3d" << " simplex elements with double precision" << std::endl; for (unsigned int order=0; order<=4; ++order) { std::cout << "order : " << order << std::endl; Dune::RaviartThomasSimplexLocalFiniteElement<3,double,double> rtSimplex(Dune::GeometryType(Dune::GeometryType::simplex, 3), order); TEST_FE(rtSimplex); } return success ? 0 : 1; } catch (const Dune::Exception &e) { std::cout << e << std::endl; return 1; } dune-localfunctions-2.5.1/dune/localfunctions/test/virtualshapefunctiontest.cc000066400000000000000000000153301313314431100301100ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #undef DUNE_VIRTUAL_SHAPEFUNCTIONS #include #include #include #include #include #include #include #include #include /** \file \brief Test the dynamically polymorphic shape function interface This file mainly tests whether the polymorphic interface can be properly instantiated, compiled and run without crashed. It does _not_ test whether the shape function sets behave correctly. */ using namespace Dune; template void syntax_check( const T& ) {} // A test function to test the local interpolation template struct TestFunction // : public VirtualFunction : public Function { void evaluate(const DomainType& in, RangeType& out) const { // May not be flexible enough to compile for all range types out = 1; } }; template void testLocalBasis(const LocalBasisVirtualInterface* localBasis) { // call each method once to test that it's there syntax_check( localBasis->order() ); unsigned int size DUNE_UNUSED = localBasis->size(); // evaluate the local basis at (0,...,0) typename T::DomainType in(0); std::vector out; localBasis->evaluateFunction(in, out); assert(out.size() == size); std::vector jacobianOut; localBasis->evaluateJacobian(in, jacobianOut); assert(jacobianOut.size() == localBasis->size()); } void testLocalCoefficients(const LocalCoefficientsVirtualInterface* localCoefficients) { if (!localCoefficients) DUNE_THROW(Dune::Exception, "Received an invalid pointer to LocalCoefficientsVirtualInterface"); if (localCoefficients->size() < 1) DUNE_THROW(Dune::Exception, "LocalCoefficients does not provide any coefficients!"); for (std::size_t i=0; isize(); i++) { // Test the localKey method // We just test whether the interface is there. Correctness is tested elsewhere syntax_check( localCoefficients->localKey(i).subEntity() ); syntax_check( localCoefficients->localKey(i).codim() ); syntax_check( localCoefficients->localKey(i).index() ); } } template void testLocalInterpolation(const LocalInterpolationVirtualInterface* localInterpolation) { // Test interpolation of a function object derived from VirtualFunction TestFunction testFunction; std::vector coefficients; localInterpolation->interpolate(testFunction, coefficients); } template struct EvaluateTest { static void test(const Interface& fe) { typedef typename Interface::Traits::LocalBasisType::Traits LBTraits; std::array d; for(unsigned int i=0; i y1; typename std::vector y2; fe.localBasis().evaluate(d,x,y1); fe.localBasis().template evaluate(d,x,y2); for(unsigned int i=0; i() and virtual evaluate() do not coincide"); EvaluateTest::test(fe); } }; template struct EvaluateTest { static void test(const Interface& fe) {} }; // Test all methods of a local finite element given as a pointer to the abstract base class template void testLocalFiniteElement(const LocalFiniteElementVirtualInterface* localFiniteElement) { // Test method type() std::cout << "Testing local finite element for a " << localFiniteElement->type() << "." << std::endl; typedef LocalFiniteElementVirtualInterface FEType; // Test the local basis const typename FEType::Traits::LocalBasisType& basis = localFiniteElement->localBasis(); testLocalBasis(&basis); // Test the local coefficients const typename FEType::Traits::LocalCoefficientsType& coeffs = localFiniteElement->localCoefficients(); testLocalCoefficients(&coeffs); // Test the interpolation const typename FEType::Traits::LocalInterpolationType& interp = localFiniteElement->localInterpolation(); testLocalInterpolation(&interp); EvaluateTest::test(*localFiniteElement); } int main (int argc, char *argv[]) try { typedef Dune::P1LocalFiniteElement::Traits::LocalBasisType::Traits LBTraits; typedef Dune::FixedOrderLocalBasisTraits::Traits C0LBTraits; typedef Dune::FixedOrderLocalBasisTraits::Traits C1LBTraits; typedef Dune::FixedOrderLocalBasisTraits::Traits C2LBTraits; const Dune::P0LocalFiniteElement p0FE(Dune::GeometryType(Dune::GeometryType::cube, 2)); const Dune::LocalFiniteElementVirtualImp > p0VFE(p0FE); testLocalFiniteElement(&p0VFE); const Dune::PQ22DLocalFiniteElement pq2FE(Dune::GeometryType(Dune::GeometryType::cube, 2)); const Dune::PQ22DLocalFiniteElement pq2FE2(pq2FE); const Dune::LocalFiniteElementVirtualImp > pq2VFE(pq2FE); testLocalFiniteElement(&pq2VFE); const Dune::LocalFiniteElementVirtualImp > p1VFE; testLocalFiniteElement(&p1VFE); testLocalFiniteElement(&p1VFE); testLocalFiniteElement(&p1VFE); const Dune::LocalFiniteElementVirtualImp< Dune::LocalFiniteElementVirtualImp > > p1VVFE; testLocalFiniteElement(&p1VVFE); testLocalFiniteElement(&p1VVFE); testLocalFiniteElement(&p1VVFE); typedef Dune::MonomialLocalFiniteElement Monom7; const Monom7 monom7FE(Dune::GeometryType(Dune::GeometryType::cube, 2)); const Dune::LocalFiniteElementVirtualImp monom7VFE(monom7FE); const Dune::LocalFiniteElementVirtualImp< Dune::LocalFiniteElementVirtualImp > monom7VVFE(monom7VFE); testLocalFiniteElement(&monom7VVFE); testLocalFiniteElement(&monom7VVFE); testLocalFiniteElement(&monom7VVFE); return 0; } catch (Exception e) { std::cout << e << std::endl; return 1; } dune-localfunctions-2.5.1/dune/localfunctions/utility/000077500000000000000000000000001313314431100231465ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/utility/CMakeLists.txt000066400000000000000000000005611313314431100257100ustar00rootroot00000000000000install(FILES basisevaluator.hh basismatrix.hh basisprint.hh coeffmatrix.hh defaultbasisfactory.hh dglocalcoefficients.hh field.hh interpolationhelper.hh l2interpolation.hh lfematrix.hh localfiniteelement.hh monomialbasis.hh multiindex.hh polynomialbasis.hh tensor.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/utility) dune-localfunctions-2.5.1/dune/localfunctions/utility/basisevaluator.hh000066400000000000000000000246031313314431100265200ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_BASISEVALUATOR_HH #define DUNE_BASISEVALUATOR_HH #include #include #include #include #include #include #include #include namespace Dune { /******************************************* * Should be removed as soon as the Tensor * classes have been revisited. See remarks * in tensor.hh (also hold true here). *******************************************/ template struct MonomialEvaluator { typedef B Basis; typedef typename Basis::Field Field; typedef typename Basis::DomainVector DomainVector; static const int dimension = Basis::dimension; static const int dimRange = Basis::dimRange; typedef std::vector Container; template< class Deriv > struct BaseIterator; template struct Iterator { typedef BaseIterator > All; typedef BaseIterator > Integrate; }; unsigned int size() const { return size_; } protected: MonomialEvaluator(const Basis &basis,unsigned int order,unsigned int size) : basis_(basis), order_(order), size_(size), container_(0) {} template void resize() { const int totalSize = Derivatives::size*size_; container_.resize(totalSize); } MonomialEvaluator(const MonomialEvaluator&); const Basis &basis_; unsigned int order_,size_; Container container_; }; template< class B > template< class Deriv > struct MonomialEvaluator< B >::BaseIterator { typedef Deriv Derivatives; typedef typename Deriv::Field Field; static const unsigned int blockSize = Deriv::size; typedef Dune::FieldVector Block; static const DerivativeLayout layout = Deriv::layout; static const unsigned int dimDomain = Deriv::dimDomain; static const unsigned int dimRange = Deriv::dimRange; typedef std::vector Container; typedef typename Container::iterator CIter; explicit BaseIterator ( Container &container ) : pos_( container.begin() ), end_( container.end() ) {} const Deriv &operator*() const { assert(!done()); return reinterpret_cast(*pos_); } const Deriv *operator->() const { return &(operator*()); } bool done () const { return pos_ == end_; } BaseIterator &operator++ () { pos_ += blockSize; return *this; } BaseIterator &operator+= ( unsigned int skip ) { pos_ += skip*blockSize; return *this; } private: CIter pos_; const CIter end_; }; template< class B > struct StandardEvaluator : public MonomialEvaluator< B > { typedef B Basis; typedef typename Basis::Field Field; typedef typename Basis::DomainVector DomainVector; typedef std::vector Container; static const int dimension = Basis::dimension; static const int dimRange = Basis::dimRange; typedef MonomialEvaluator Base; template struct Iterator : public Base::template Iterator {}; StandardEvaluator(const Basis &basis) : Base(basis,basis.order(),basis.size()) {} template typename Iterator::All evaluate(const DVector &x) { Base::template resize(); basis_.template evaluate(x,&(container_[0])); return typename Iterator::All(container_); } typename Iterator<0>::Integrate integrate() { Base::template resize<0>(); basis_.integrate(&(container_[0])); return typename Iterator<0>::Integrate(container_); } protected: StandardEvaluator ( const Basis &basis, unsigned int size ) : Base( basis, basis.order(), size ) {} private: StandardEvaluator(const StandardEvaluator&); using Base::basis_; using Base::container_; }; #if 0 // OLD OLD template< class B, class Fill > struct VecEvaluator : public StandardEvaluator< B > { typedef B Basis; typedef typename Basis::Field Field; static const int dimension = Basis::dimension; static const int dimRange = Basis::dimRange*Fill::dimRange; typedef typename Basis::DomainVector DomainVector; typedef std::vector Container; typedef StandardEvaluator Base; template struct Iterator { typedef typename Base::template BaseIterator > All; }; VecEvaluator ( const Basis &basis, const Fill &fill ) : Base( basis, basis.size() ), fill_( fill ), size_( basis.size()*dimRange ) {} template typename Iterator::All evaluate(const DomainVector &x) { resize< deriv >(); fill_.template apply( x,Base::template evaluate(x), vecContainer_ ); std::vector >& derivContainer = reinterpret_cast >&>(vecContainer_); return typename Iterator::All(derivContainer); } template typename Iterator::All evaluate(const DVector &x) { resize< deriv >(); fill_.template apply( x,Base::template evaluate(x), vecContainer_ ); std::vector >& derivContainer = reinterpret_cast >&>(vecContainer_); return typename Iterator::All(derivContainer); } unsigned int size() const { return size_; } protected: VecEvaluator ( const Basis &basis, const Fill &fill, unsigned int size ) : Base( basis, basis.size() ), fill_( fill ), size_( size ) { resize< 2 >(); } template void resize() { const int totalSize = Derivatives::size*size_; vecContainer_.resize(totalSize); } VecEvaluator(const VecEvaluator&); Container vecContainer_; const Fill &fill_; unsigned int size_; }; template struct DiagonalFill; template struct DiagonalFill { static const DerivativeLayout layout = derivative; static const int dimRange = dimR; template void apply(const Domain &x, Iter iter,std::vector &vecContainer) const { typedef std::vector Container; typename Container::iterator vecIter = vecContainer.begin(); for ( ; !iter.done(); ++iter) { const typename Iter::Block &block = iter->block(); for (int r1=0; r1(r1,x,block,b,vecIter); } } } template void apply(int r1, const Domain &x, const Block &block,unsigned int &b, VecIter &vecIter) const { unsigned int bStart = b; unsigned int bEnd = b+Block::size; apply(r1,x,block,bStart,bEnd,vecIter); b=bEnd; } template void apply(int r1, const Domain &x,const Block &block, unsigned int bStart, unsigned int bEnd, VecIter &vecIter) const { for (int r2=0; r2 struct DiagonalFill { static const DerivativeLayout layout = value; static const int dimRange = dimR; template void apply(const Domain &x, Iter iter,std::vector &vecContainer) const { typedef std::vector Container; typename Container::iterator vecIter = vecContainer.begin(); for ( ; !iter.done(); ++iter) { const typename Iter::Block &block = iter->block(); for (int r1=0; r1(std::integral_constant(),r1,x,block,b,vecIter); } } } template void apply(const integral_constat&, int r1, const Domain &x, const Block &block,unsigned int &b, VecIter &vecIter) const { apply(std::integral_constant(),r1,x,block,b,vecIter); unsigned int bStart = b; unsigned int bEnd = b+LFETensor::size; apply(r1,x,block,bStart,bEnd,vecIter); b=bEnd; } template void apply(const std::integral_constant&, int r1, const Domain &x, const Block &block,unsigned int &b, VecIter &vecIter) const { apply(r1,x,block,b,b+1,vecIter); ++b; } template void apply(int r1, const Domain &x,const Block &block, unsigned int bStart, unsigned int bEnd, VecIter &vecIter) const { for (int r2=0; r2 struct VectorialEvaluator : public VecEvaluator > { typedef DiagonalFill Fill; typedef VecEvaluator< B,Fill > Base; VectorialEvaluator(const B &basis) : Base(basis,fill_,basis.size()*dimR) {} private: Fill fill_; }; #endif // OLD OLD } #endif dune-localfunctions-2.5.1/dune/localfunctions/utility/basismatrix.hh000066400000000000000000000140761313314431100260250ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_BASISMATRIX_HH #define DUNE_BASISMATRIX_HH #include #include #include #include #include namespace Dune { /**************************************** * A dense matrix representation of a ''polynomial'' * basis. Its represent a basis as a linear * combination of a second basis, i.e., a * monomial basis. It is simular to the PolynomialBasis * but it not derived from the LocalBasis class. * It is used to define a ''pre basis''. ****************************************/ template< class PreBasis, class Interpolation, class Field > struct BasisMatrix; template< class PreBasis, class Interpolation, class Field > struct BasisMatrixBase : public LFEMatrix { typedef LFEMatrix Matrix; BasisMatrixBase( const PreBasis& preBasis, const Interpolation& localInterpolation ) : cols_(preBasis.size()) { localInterpolation.interpolate( preBasis, *this ); if ( !Matrix::invert() ) { DUNE_THROW(MathError, "While computing basis a singular matrix was constructed!"); } } unsigned int cols () const { return cols_; } unsigned int rows () const { return Matrix::rows(); } private: unsigned int cols_; }; template< class Topology, class F, class Interpolation, class Field > struct BasisMatrix< const MonomialBasis< Topology, F >, Interpolation, Field > : public BasisMatrixBase< const MonomialBasis< Topology, F >, Interpolation, Field > { typedef const MonomialBasis< Topology, F > PreBasis; typedef BasisMatrixBase Base; typedef typename Base::Matrix Matrix; BasisMatrix( const PreBasis& preBasis, const Interpolation& localInterpolation ) : Base(preBasis, localInterpolation) {} template void row( const unsigned int row, Vector &vec ) const { const unsigned int N = Matrix::rows(); assert( Matrix::cols() == N && vec.size() == N ); // note: that the transposed matrix is computed, // and is square for (unsigned int i=0; i struct BasisMatrix< const Dune::VirtualMonomialBasis< dim, F >, Interpolation, Field > : public BasisMatrixBase< const VirtualMonomialBasis< dim, F >, Interpolation, Field > { typedef const VirtualMonomialBasis< dim, F > PreBasis; typedef BasisMatrixBase Base; typedef typename Base::Matrix Matrix; BasisMatrix( const PreBasis& preBasis, const Interpolation& localInterpolation ) : Base(preBasis, localInterpolation) {} template void row( const unsigned int row, Vector &vec ) const { const unsigned int N = Matrix::rows(); assert( Matrix::cols() == N && vec.size() == N ); // note: that the transposed matrix is computed, // and is square for (unsigned int i=0; i struct BasisMatrix< const PolynomialBasis, Interpolation, Field > : public BasisMatrixBase< const PolynomialBasis, Interpolation, Field > { typedef const PolynomialBasis PreBasis; typedef BasisMatrixBase Base; typedef typename Base::Matrix Matrix; BasisMatrix( const PreBasis& preBasis, const Interpolation& localInterpolation ) : Base(preBasis, localInterpolation), preBasis_(preBasis) {} unsigned int cols() const { return preBasis_.matrix().baseSize() ; } template void row( const unsigned int row, Vector &vec ) const { assert( Matrix::rows() == Matrix::cols() ); assert( vec.size() == preBasis_.matrix().baseSize() ); assert( Matrix::cols() == preBasis_.size() ); for (unsigned int j=0; j struct BasisMatrix< const PolynomialBasisWithMatrix, Interpolation, Field > : public BasisMatrixBase< const PolynomialBasisWithMatrix, Interpolation, Field > { typedef const PolynomialBasisWithMatrix PreBasis; typedef BasisMatrixBase Base; typedef typename Base::Matrix Matrix; BasisMatrix( const PreBasis& preBasis, const Interpolation& localInterpolation ) : Base(preBasis, localInterpolation), preBasis_(preBasis) {} unsigned int cols() const { return preBasis_.matrix().baseSize() ; } unsigned int rows () const { assert( Matrix::rows() == preBasis_.matrix().size() ); return preBasis_.matrix().size()*CM::blockSize ; } template void row( const unsigned int row, Vector &vec ) const { unsigned int r = row / CM::blockSize; assert( r < Matrix::rows() ); assert( Matrix::rows() == Matrix::cols() ); assert( vec.size() == preBasis_.matrix().baseSize() ); assert( Matrix::cols() == preBasis_.size() ); for (unsigned int j=0; j #include namespace Dune { /********************************************** * Methods for printing a PolynomialBasis. * Is achieved by using the MultiIndex class as * Field type and printing the results. * The basis and higher order derivatives can be * printed. This could be the basis for printing * routings providing C++ or matlab methods * for computing the basisfunctions for given * orders or reference elements. **********************************************/ // default argument does not work for gcc 4.1.2 // template template void basisPrint(std::ostream &out, typename BasisFactory::Object &basis) { typedef typename BasisFactory::Object Basis; const int dimension = Basis::dimension; typedef MultiIndex< dimension, PrintField > Field; typedef typename BasisFactory::template EvaluationBasisFactory::Type MIBasisFactory; typedef typename MIBasisFactory::Object MIBasis; typedef typename Basis::CoefficientMatrix CMatrix; typedef PolynomialBasis, CMatrix > PrintBasis; MIBasis *miBasis = MIBasisFactory::create( Dune::GeometryType( basis.basis().topologyId(),dimension ),basis.basis().order()); PrintBasis printBasis(*miBasis,basis.matrix(),basis.size()); unsigned int size = printBasis.size(); out << "% Number of base functions: " << size << std::endl; out << "% Derivative order: " << deriv << std::endl; /* std::vector< FieldVector< LFETensor,PrintBasis::dimRange> > y( size ); */ std::vector< FieldVector< FieldVector::size>, PrintBasis::dimRange> > y( size ); FieldVector< Field, dimension > x; for( int i = 0; i < dimension; ++i ) x[ i ].set( i, 1 ); printBasis.template evaluateSingle( x, y ); for (unsigned int i=0; i template void basisPrint(std::ostream &out, typename BasisFactory::Key &key) { typename BasisFactory::Object *basis = BasisFactory::create(key); basisPrint(out,*basis); BasisFactory::release(basis); } } #endif // BASISPRINT dune-localfunctions-2.5.1/dune/localfunctions/utility/coeffmatrix.hh000066400000000000000000000166721313314431100260120ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_COEFFMATRIX_HH #define DUNE_COEFFMATRIX_HH #include #include #include #include #include #include namespace Dune { /************************************************* * Default class for storing a coefficient matrix * for the PolynomialBasis. Basically a simple * CRS structure is used. The additional complexity * is due to the storage and efficient evaluation * of higher order derivatives. See the remarks * in tensor.hh which also hold true for this file. *************************************************/ template struct Mult { typedef Field2 BasisEntry; static void add(const Field &vec1, const BasisEntry &vec2, BasisEntry &res) { res += vec1*vec2; } }; template struct Mult< Field,FieldVector > { typedef FieldVector BasisEntry; static void add(const Field &vec1, const BasisEntry &vec2, BasisEntry &res) { res.axpy(vec1,vec2); } }; template< class F , unsigned int bSize > class SparseCoeffMatrix { public: typedef F Field; static const unsigned int blockSize = bSize; typedef SparseCoeffMatrix This; SparseCoeffMatrix() : coeff_(0), rows_(0), skip_(0), numRows_(0), numCols_(0) {} ~SparseCoeffMatrix() { delete [] coeff_; delete [] rows_; delete [] skip_; } unsigned int size () const { return numRows_/blockSize; } unsigned int baseSize () const { return numCols_; } template< class BasisIterator, class FF> void mult ( const BasisIterator &x, unsigned int numLsg, FF *y ) const { typedef typename BasisIterator::Derivatives XDerivatives; assert( numLsg*blockSize <= (size_t)numRows_ ); unsigned int row = 0; Field *pos = rows_[ 0 ]; unsigned int *skipIt = skip_; XDerivatives val; for( size_t i = 0; i < numLsg; ++i) { for( unsigned int r = 0; r < blockSize; ++r, ++row ) { val = 0; BasisIterator itx = x; for( ; pos != rows_[ row+1 ]; ++pos, ++skipIt ) { itx += *skipIt; val.axpy(*pos,*itx); } DerivativeAssign::apply(r,val,*(y+i*XDerivatives::size*blockSize)); } } } template< class BasisIterator, class Vector> void mult ( const BasisIterator &x, Vector &y ) const { typedef typename Vector::value_type YDerivatives; typedef typename BasisIterator::Derivatives XDerivatives; size_t numLsg = y.size(); assert( numLsg*blockSize <= (size_t)numRows_ ); unsigned int row = 0; Field *pos = rows_[ 0 ]; unsigned int *skipIt = skip_; XDerivatives val; for( size_t i = 0; i < numLsg; ++i) { for( unsigned int r = 0; r < blockSize; ++r, ++row ) { val = 0; BasisIterator itx = x; for( ; pos != rows_[ row+1 ]; ++pos, ++skipIt ) { itx += *skipIt; val.axpy(*pos,*itx); } DerivativeAssign::apply(r,val,y[i]); } } } template void mult ( const BasisIterator &x, Vector &y ) const { typedef typename Vector::value_type YDerivatives; typedef typename BasisIterator::Derivatives XDerivatives; typedef FieldVector XLFETensor; size_t numLsg = y.size(); assert( numLsg*blockSize <= (size_t)numRows_ ); unsigned int row = 0; Field *pos = rows_[ 0 ]; unsigned int *skipIt = skip_; for( size_t i = 0; i < numLsg; ++i) { XLFETensor val(typename XDerivatives::Field(0)); for( unsigned int r = 0; r < blockSize; ++r, ++row ) { BasisIterator itx = x; for( ; pos != rows_[ row+1 ]; ++pos, ++skipIt ) { itx += *skipIt; LFETensorAxpy::apply(r,*pos,*itx,val); } } field_cast(val,y[i]); } } template< class RowMatrix > void fill ( const RowMatrix &mat, bool verbose=false ) { numRows_ = mat.rows(); numCols_ = mat.cols(); unsigned int size = numRows_*numCols_; delete [] coeff_; delete [] rows_; delete [] skip_; Field* coeff = new Field[ size ]; // we always initialize the next skip entry to zero, // including the one following the end, so allocate // size+1 entries so we will stay within the bounds. unsigned int *skip = new unsigned int[ size+1 ]; rows_ = new Field*[ numRows_+1 ]; std::vector row( numCols_ ); rows_[ 0 ] = coeff; Field *cit = coeff; unsigned int *sit = skip; for( unsigned int r = 0; r < numRows_; ++r ) { *sit = 0; mat.row( r, row ); for( unsigned int c = 0; c < numCols_; ++c ) { const Field &val = row[c]; if (val < Zero() || Zero() < val) { *cit = val; ++sit; ++cit; *sit = 1; } else { ++(*sit); } } rows_[ r+1 ] = cit; } assert( size_t(rows_[numRows_]-rows_[0]) <= size_t(size) ); size = rows_[numRows_]-rows_[0]; coeff_ = new Field[ size ]; skip_ = new unsigned int[ size ]; for (unsigned int i=0; i void addRow( unsigned int k, const Field &a, Vector &b) const { assert(k( (*pos)*a ); // field_cast } } private: SparseCoeffMatrix ( const This &other ) : numRows_( other.numRows_ ), numCols_( other.numCols_ ) { const unsigned int size = other.rows_[numRows_]-other.rows_[0]; coeff_ = new Field[ size ]; rows_ = new Field*[ numRows_+1 ]; skip_ = new unsigned int[ size ]; for (unsigned int i=0; i #include #include #include namespace Dune { struct Identity { template static T apply( const T &t ) { return t; } }; /************************************************ * Class for providing a factory for basis * functions over the set of reference elements. * Is based on the TopologyFactory but additionally * provides rebindes of the field type. * The user provides factories for the pre basis and the * interpolations. The default construction process of * the basis is performed in this class. ************************************************/ template< class PreBFactory, class InterpolFactory, unsigned int dim, unsigned int dimR, class SF, class CF, class PreBasisKeyExtractor = Identity > struct DefaultBasisFactory; template< class PreBFactory, class InterpolFactory, unsigned int dim, unsigned int dimR, class SF, class CF, class PreBasisKeyExtractor > struct DefaultBasisFactoryTraits { static const unsigned int dimension = dim; static const unsigned int dimRange = dimR; typedef PreBFactory PreBasisFactory; typedef typename PreBasisFactory::Object PreBasis; typedef InterpolFactory InterpolationFactory; typedef typename InterpolationFactory::Object Interpolation; typedef typename PreBasisFactory::template EvaluationBasisFactory::Type MonomialBasisFactory; typedef typename MonomialBasisFactory::Object MonomialBasis; typedef StandardEvaluator< MonomialBasis > Evaluator; typedef PolynomialBasisWithMatrix< Evaluator, SparseCoeffMatrix< SF, dimRange > > Basis; typedef const Basis Object; typedef typename InterpolationFactory::Key Key; typedef DefaultBasisFactory Factory; }; template< class PreBFactory, class InterpolFactory, unsigned int dim, unsigned int dimR, class SF, class CF, class PreBasisKeyExtractor > struct DefaultBasisFactory : public TopologyFactory< DefaultBasisFactoryTraits< PreBFactory,InterpolFactory,dim,dimR,SF,CF,PreBasisKeyExtractor > > { typedef DefaultBasisFactoryTraits< PreBFactory,InterpolFactory,dim,dimR,SF,CF,PreBasisKeyExtractor > Traits; static const unsigned int dimension = Traits::dimension; static const unsigned int dimRange = Traits::dimRange; typedef SF StorageField; typedef CF ComputeField; typedef typename Traits::Basis Basis; typedef typename Traits::PreBasisFactory PreBasisFactory; typedef typename Traits::Object Object; typedef typename Traits::Key Key; template struct EvaluationBasisFactory { typedef typename Traits::PreBasisFactory::template EvaluationBasisFactory::Type Type; }; template< class Topology > static Object *createObject ( const Key &key ) { const typename PreBasisFactory::Key preBasisKey = PreBasisKeyExtractor::apply(key); const typename Traits::PreBasis *preBasis = Traits::PreBasisFactory::template create( preBasisKey ); const typename Traits::Interpolation *interpol = Traits::InterpolationFactory::template create( key ); BasisMatrix< typename Traits::PreBasis, typename Traits::Interpolation, ComputeField > matrix( *preBasis, *interpol ); const typename Traits::MonomialBasis *monomialBasis = Traits::MonomialBasisFactory::template create< Topology >( preBasis->order() ); Basis *basis = new Basis( *monomialBasis ); basis->fill( matrix ); Traits::InterpolationFactory::release(interpol); Traits::PreBasisFactory::release(preBasis); return basis; } //! release the object returned by the create methods static void release( Object *object) { const typename Traits::MonomialBasis *monomialBasis = &(object->basis()); delete object; Traits::MonomialBasisFactory::release( monomialBasis ); } }; } #endif // #ifndef DUNE_DEFAULTBASISFACTORY_HH dune-localfunctions-2.5.1/dune/localfunctions/utility/dglocalcoefficients.hh000066400000000000000000000044201313314431100274560ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGLOCALCOEFFICIENTS_HH #define DUNE_DGLOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { // DGLocalCoefficients // ------------------- /** * @brief A class providing local coefficients for dg spaces **/ class DGLocalCoefficients { typedef DGLocalCoefficients This; public: //! construct local keys for n basis functions DGLocalCoefficients ( const unsigned int n ) : localKey_( n ) { for( unsigned i = 0; i < n; ++i ) localKey_[ i ] = LocalKey( 0, 0, i ); } const LocalKey &localKey ( const unsigned int i ) const { assert( i < size() ); return localKey_[ i ]; } unsigned int size () const { return localKey_.size(); } private: std::vector< LocalKey > localKey_; }; // DGLocalCoefficientsFactory // -------------------------- /** * @brief A factory class for the dg local coefficients. **/ template< class BasisCreator > struct DGLocalCoefficientsFactory; template< class BasisFactory > struct DGLocalCoefficientsFactoryTraits { static const unsigned int dimension = BasisFactory::dimension; typedef typename BasisFactory::Key Key; typedef DGLocalCoefficients LocalCoefficients; typedef const DGLocalCoefficients Object; typedef DGLocalCoefficientsFactory Factory; }; template< class BasisFactory > struct DGLocalCoefficientsFactory : public TopologyFactory< DGLocalCoefficientsFactoryTraits > { typedef DGLocalCoefficientsFactoryTraits Traits; static const unsigned int dimension = Traits::dimension; typedef typename Traits::Key Key; typedef typename Traits::Object Object; template< class Topology > static Object *createObject ( const Key &key ) { const typename BasisFactory::Object *basis = BasisFactory::template create< Topology >( key ); Object *coefficients = new Object( basis->size() ); BasisFactory::release( basis ); return coefficients; } }; } #endif // #ifndef DUNE_DGLOCALCOEFFICIENTS_HH dune-localfunctions-2.5.1/dune/localfunctions/utility/field.hh000066400000000000000000000164211313314431100245560ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_UTILITY_FIELD_HH #define DUNE_LOCALFUNCTIONS_UTILITY_FIELD_HH #include #include #include namespace Dune { // Unity // ----- /** * @brief A class representing the unit of a given Field * * This class can be used to assign the unit element to an * instance of a given Field also operators for +/- with * unit element are provided. Also 1/f can be evaluated. * Through specialization this class can be used also in the case that the * integer 1 is not automatically converted to the unit * element of the Field - the default implementation **/ template< class Field > struct Unity { operator Field () const { return Field( 1 ); } }; template< class Field > Field operator+ ( const Unity< Field > &u, const Field &f ) { return (Field)u + f; } template< class Field > Field operator- ( const Unity< Field > &u, const Field &f ) { return (Field)u - f; } template< class Field > Field operator* ( const Unity< Field > &u, const Field &f ) { return f; } template< class Field > Field operator/ ( const Unity< Field > &u, const Field &f ) { return (Field)u / f; } // Zero // ---- /** * @brief A class representing the zero of a given Field * * This class can be used to assign the zero element to an * instance of a given Field. An epsilon is also * provided for the comparison operators. * This class can be used also in the case that the * integer 0 is not automatically converted to the zero * element of the Field and the epsilon can be changed * depending on the accuracy of the Field type. **/ template< class Field > struct Zero { operator Field () const { return Field( 0 ); } static const Field epsilon() { return Field(1e-12); } }; #if HAVE_GMP template< unsigned int precision > struct Zero< GMPField< precision > > { typedef GMPField< precision > Field; operator Field () const { return Field( 0 ); } static const Field epsilon() { return Field(1e-20); } }; #endif template< class Field > inline bool operator == ( const Zero< Field > &, const Field &f ) { return ( f < Zero::epsilon() && f > -Zero::epsilon() ); } template< class Field > inline bool operator == ( const Field &f, const Zero< Field > &z) { return ( z == f ); } template< class Field > inline bool operator< ( const Zero< Field > &, const Field &f ) { return f > Zero::epsilon(); } template< class Field > inline bool operator< ( const Field &f, const Zero< Field > & ) { return f < -Zero::epsilon(); } template< class Field > inline bool operator> ( const Zero< Field > &z, const Field &f ) { return f < z; } template< class Field > inline bool operator> ( const Field &f, const Zero< Field > &z ) { return z < f; } // field_cast // ---------- /** * @brief a helper class to cast from one field * to another * * This cast can be used for assignement between * different field types, including for example * between FieldVectors with different fields. * Specially the conversion from a special type * e.g. gmp to build in types are provided, the * other direction can be more easily handled by * the special field type implementation. **/ template< class F2, class F1 > inline void field_cast ( const F1 &f1, F2 &f2 ) { f2 = f1; } #if HAVE_GMP template< unsigned int precision > inline void field_cast ( const Dune::GMPField< precision > &f1, double &f2 ) { f2 = f1.get_d(); } template< unsigned int precision > inline void field_cast ( const Dune::GMPField< precision > &f1, long double &f2 ) { f2 = f1.get_d(); } #endif template< class F2, class F1, int dim > inline void field_cast ( const Dune::FieldVector< F1, dim > &f1, Dune::FieldVector< F2, dim > &f2 ) { for( int d = 0; d < dim; ++d ) field_cast( f1[ d ], f2[ d ] ); } template< class F2, class F1 > inline void field_cast ( const Dune::FieldVector< F1, 1 > &f1, F2 &f2 ) { field_cast( f1[ 0 ], f2 ); } template< class F2, class F1 > inline void field_cast ( const F1 &f1, Dune::FieldVector< F2, 1 > &f2 ) { field_cast( f1, f2[ 0 ] ); } template< class F2, class F1, int rdim, int cdim > inline void field_cast ( const Dune::FieldMatrix< F1, rdim, cdim > &f1, Dune::FieldMatrix< F2, rdim, cdim > &f2 ) { for( int r = 0; r < rdim; ++r ) field_cast( f1[ r ], f2[ r ] ); } template< class F2, class F1 > inline void field_cast ( const Dune::FieldMatrix &f1, Dune::FieldMatrix< F2, 1,1 > &f2 ) { field_cast( f1[ 0 ][ 0 ], f2[ 0 ][ 0 ] ); } template< class F2, class F1 > inline void field_cast ( const Dune::FieldMatrix< F1, 1,1 > &f1, F2 &f2 ) { field_cast( f1[ 0 ][ 0 ], f2 ); } template< class F2, class F1 > inline void field_cast ( const F1 &f1, Dune::FieldMatrix< F2, 1,1 > &f2 ) { field_cast( f1, f2[ 0 ][ 0 ] ); } template< class F2, class F1 > inline void field_cast ( const Dune::FieldVector &f1, Dune::FieldMatrix< F2, 1,1 > &f2 ) { field_cast( f1[ 0 ], f2[ 0 ][ 0 ] ); } template< class F2, class F1 > inline void field_cast ( const Dune::FieldMatrix &f1, Dune::FieldVector< F2, 1 > &f2 ) { field_cast( f1[ 0 ][ 0 ], f2[ 0 ] ); } template< class F2, class F1 > inline void field_cast ( const Dune::FieldVector< F1, 1 > &f1, Dune::FieldVector &f2 ) { field_cast( f1[ 0 ], f2[ 0 ] ); } template< class F2,class V > struct FieldCast { typedef F2 type; }; template< class F2,class F1,int dim > struct FieldCast< F2, Dune::FieldVector > { typedef Dune::FieldVector type; }; template< class F2,class F1,int dim1, int dim2> struct FieldCast< F2, Dune::FieldMatrix > { typedef Dune::FieldMatrix type; }; template< class F2,class V > inline typename FieldCast::type field_cast ( const V &f1 ) { typename FieldCast::type f2; field_cast( f1, f2 ); return f2; } // Precision // this is not a perfect solution to obtain the // precision of a field - definition is not clear // to be removed // --------- template struct Precision; template<> struct Precision< double > { static const unsigned int value = 64; }; template<> struct Precision< long double > { static const unsigned int value = 80; }; template<> struct Precision< float > { static const unsigned int value = 32; }; #if HAVE_GMP template< unsigned int precision > struct Precision< GMPField< precision > > { static const unsigned int value = precision; }; #endif // ComputeField // ------------ template struct ComputeField { typedef Field Type; }; #if HAVE_GMP template< unsigned int precision, unsigned int sum > struct ComputeField< GMPField< precision >, sum > { typedef GMPField Type; }; #endif } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_UTILITY_FIELD_HH dune-localfunctions-2.5.1/dune/localfunctions/utility/interpolationhelper.hh000066400000000000000000000062101313314431100275550ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef GENERIC_INTERPOLATIONHELPER_HH #define GENERIC_INTERPOLATIONHELPER_HH #include #include #include namespace Dune { // A small helper class to avoid having to // write the interpolation twice (once for function // and once for a basis) template< class F, unsigned int dimension > struct InterpolationHelper { template struct Helper; }; template template struct InterpolationHelper::Helper // Func is of Function type { typedef std::vector< Dune::FieldVector > Result; Helper(const Func & func, Vector &vec) : func_(func), vec_(vec), tmp_(1) {} const typename Vector::value_type &operator()(unsigned int row,unsigned int col) { return vec_[row]; } template void set(unsigned int row,unsigned int col, const Fy &val) { assert(col==0); assert(row void add(unsigned int row,unsigned int col, const Fy &val) { assert(col==0); assert(row(val); } template const Result &evaluate(const DomainVector &x) const { typename Func::DomainType xx ; typename Func::RangeType ff ; field_cast(x,xx); func_.evaluate(xx,ff); field_cast(ff, tmp_[0] ); return tmp_; } unsigned int size() const { return 1; } const Func &func_; Vector &vec_; mutable Result tmp_; }; template template struct InterpolationHelper::Helper // Func is of Basis type { typedef std::vector< Dune::FieldVector > Result; Helper(const Basis & basis, Matrix &matrix) : basis_(basis), matrix_(matrix), tmp_(basis.size()) {} const F &operator()(unsigned int row,unsigned int col) const { return matrix_(row,col); } F &operator()(unsigned int row,unsigned int col) { return matrix_(row,col); } template void set(unsigned int row,unsigned int col, const Fy &val) { assert(col void add(unsigned int row,unsigned int col, const Fy &val) { assert(col const Result &evaluate(const DomainVector &x) const { basis_.template evaluate<0>(x,tmp_); return tmp_; } unsigned int size() const { return basis_.size(); } const Basis &basis_; Matrix &matrix_; mutable Result tmp_; }; } #endif // GENERIC_INTERPOLATIONHELPER_HH dune-localfunctions-2.5.1/dune/localfunctions/utility/l2interpolation.hh000066400000000000000000000162571313314431100266270ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_L2INTERPOLATION_HH #define DUNE_L2INTERPOLATION_HH #include #include #include namespace Dune { /** * @brief A local L2 interpolation taking a test basis and a quadrature * rule. * * This class computes a local interpolation where the coefficients * are of the form: * c = M^{-1}b * - M is the mass matrix with respect to the given basis and * - b = int f phi (where phi are the basis functions). * Thus the resulting local function u=c.varphi is defined through * the l2 interpolation int u phi = in f phi for all phi in the * base function set. * The third template argument can be used to specify that the * mass matrix is the unit matrix (onb=true). **/ template< class B, class Q, bool onb > struct LocalL2Interpolation; template< class B, class Q > class LocalL2InterpolationBase { typedef LocalL2InterpolationBase< B, Q > This; public: typedef B Basis; typedef Q Quadrature; static const unsigned int dimension = Basis::dimension; template< class Function, class DofField > void interpolate ( const Function &function, std::vector< DofField > &coefficients ) const { typedef typename Quadrature::iterator Iterator; typedef FieldVector< DofField, Basis::dimRange > RangeVector; const unsigned int size = basis().size(); static std::vector< RangeVector > basisValues( size ); coefficients.resize( size ); basisValues.resize( size ); for( unsigned int i = 0; i < size; ++i ) coefficients[ i ] = Zero< DofField >(); const Iterator end = quadrature().end(); for( Iterator it = quadrature().begin(); it != end; ++it ) { basis().evaluate( it->position(), basisValues ); typename Function::RangeType val; function.evaluate( field_cast(it->position()), val ); RangeVector factor = field_cast< DofField >( val ); factor *= field_cast< DofField >( it->weight() ); for( unsigned int i = 0; i < size; ++i ) coefficients[ i ] += factor * basisValues[ i ]; } } const Basis &basis () const { return basis_; } const Quadrature &quadrature () const { return quadrature_; } protected: LocalL2InterpolationBase ( const Basis &basis, const Quadrature &quadrature ) : basis_( basis ), quadrature_( quadrature ) {} const Basis &basis_; const Quadrature &quadrature_; }; template< class B, class Q > struct LocalL2Interpolation : public LocalL2InterpolationBase { typedef LocalL2InterpolationBase Base; template< class BasisFactory, bool onb > friend class LocalL2InterpolationFactory; using typename Base::Basis; using typename Base::Quadrature; private: LocalL2Interpolation ( const typename Base::Basis &basis, const typename Base::Quadrature &quadrature ) : Base(basis,quadrature) {} }; template< class B, class Q > struct LocalL2Interpolation : public LocalL2InterpolationBase { typedef LocalL2InterpolationBase Base; template< class BasisFactory, bool onb > friend class LocalL2InterpolationFactory; using typename Base::Basis; using typename Base::Quadrature; template< class Function, class DofField > void interpolate ( const Function &function, std::vector< DofField > &coefficients ) const { const unsigned size = Base::basis().size(); Base::interpolate(function,val_); coefficients.resize( size ); for (unsigned int i=0; i(massMatrix_(i,j)*val_[j]); } } } private: LocalL2Interpolation ( const typename Base::Basis &basis, const typename Base::Quadrature &quadrature ) : Base(basis,quadrature), val_(basis.size()), massMatrix_() { typedef FieldVector< Field, Base::Basis::dimRange > RangeVector; typedef typename Base::Quadrature::iterator Iterator; const unsigned size = basis.size(); std::vector< RangeVector > basisValues( size ); massMatrix_.resize( size,size ); for (unsigned int i=0; iposition(), basisValues ); for (unsigned int i=0; iweight(); } if ( !massMatrix_.invert() ) { DUNE_THROW(MathError, "Mass matrix singular in LocalL2Interpolation"); } } typedef typename Base::Basis::StorageField Field; typedef FieldVector< Field, Base::Basis::dimRange > RangeVector; typedef LFEMatrix MassMatrix; mutable std::vector val_; MassMatrix massMatrix_; }; /** * @brief A factory class for the local l2 interpolations * taking a basis factory. **/ template< class BasisFactory, bool onb > struct LocalL2InterpolationFactory; template< class BasisFactory, bool onb > struct LocalL2InterpolationFactoryTraits { static const unsigned int dimension = BasisFactory::dimension; // typedef typename BasisFactory::StorageField Field; typedef double Field; typedef QuadratureRule Quadrature; typedef QuadratureRules QuadratureProvider; typedef typename BasisFactory::Key Key; typedef typename BasisFactory::Object Basis; typedef LocalL2Interpolation< Basis, Quadrature, onb > LocalInterpolation; typedef const LocalInterpolation Object; typedef LocalL2InterpolationFactory Factory; }; template< class BasisFactory, bool onb > struct LocalL2InterpolationFactory : public TopologyFactory< LocalL2InterpolationFactoryTraits > { typedef LocalL2InterpolationFactoryTraits Traits; static const unsigned int dimension = Traits::dimension; typedef typename Traits::Key Key; typedef typename Traits::Basis Basis; typedef typename Traits::Object Object; typedef typename Traits::Field Field; typedef typename Traits::Quadrature Quadrature; template< class Topology > static Object *createObject ( const Key &key ) { Dune::GeometryType gt(Topology::id, Topology::dimension); const Basis *basis = BasisFactory::template create< Topology >( key ); const Quadrature & quadrature = Traits::QuadratureProvider::rule(gt, 2*basis->order()+1); return new Object( *basis, quadrature ); } static void release ( Object *object ) { const Basis &basis = object->basis(); BasisFactory::release( &basis ); delete object; } }; } #endif // #ifndef DUNE_L2INTERPOLATION_HH dune-localfunctions-2.5.1/dune/localfunctions/utility/lfematrix.hh000066400000000000000000000073351313314431100254720ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_UTILITY_LFEMATRIX_HH #define DUNE_LOCALFUNCTIONS_UTILITY_LFEMATRIX_HH #include #include #include "field.hh" namespace Dune { template< class F > class LFEMatrix { typedef LFEMatrix< F > This; typedef std::vector< F > Row; typedef std::vector RealMatrix; public: typedef F Field; operator const RealMatrix & () const { return matrix_; } operator RealMatrix & () { return matrix_; } template void row( const unsigned int row, Vector &vec ) const { assert(row p(rows()); for (unsigned int j=0; j max ) { max = std::abs( (*this)(i,j) ); r = i; } } if (max == Zero()) return false; // row swap if (r > j) { for (unsigned int k=0; k()/(*this)(j,j); for (unsigned int i=0; i inline std::ostream &operator<<(std::ostream &out, const LFEMatrix &mat) { for (unsigned int r=0; r(mat(r,0)); for (unsigned int c=1; c(mat(r,c)); } out << std::endl; } return out; } } #endif // #ifndef DUNE_LOCALFUNCTIONS_UTILITY_LFEMATRIX_HH dune-localfunctions-2.5.1/dune/localfunctions/utility/localfiniteelement.hh000066400000000000000000000140371313314431100273370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GENERIC_LOCALFINITEELEMENT_HH #define DUNE_GENERIC_LOCALFINITEELEMENT_HH #include #include #include #include namespace Dune { /** * \brief A LocalFiniteElement implementation based on three * TopologyFactories providing the LocalBasis, LocalCoefficients, * and LocalInterpolations. Note the key type for all three * factories must coincide. **/ template< class BasisF, class CoeffF, class InterpolF> struct GenericLocalFiniteElement { typedef GenericLocalFiniteElement This; typedef LocalFiniteElementTraits< typename BasisF::Object, typename CoeffF::Object, typename InterpolF::Object > Traits; typedef typename BasisF::Key Key; static const unsigned int dimDomain = BasisF::dimension; typedef BasisF BasisFactory; typedef CoeffF CoefficientFactory; typedef InterpolF InterpolationFactory; static_assert(std::is_same::value, "incompatible keys between BasisCreator and CoefficientsCreator"); static_assert(std::is_same::value, "incompatible keys between BasisCreator and InterpolationCreator" ); /** \todo Please doc me */ GenericLocalFiniteElement ( const GeometryType >, const Key &key ) : topologyId_( gt.id() ), key_( key ), finiteElement_() { Impl::IfTopology< FiniteElement::template Maker, dimDomain >::apply( topologyId_, key_, finiteElement_ ); } /** \todo Please doc me */ GenericLocalFiniteElement ( const GenericLocalFiniteElement &other ) : topologyId_( other.topologyId_ ), key_( other.key_ ), finiteElement_() { Impl::IfTopology< FiniteElement::template Maker, dimDomain >::apply( topologyId_, key_, finiteElement_ ); } ~GenericLocalFiniteElement() { finiteElement_.release(); } /** \todo Please doc me ! */ const typename Traits::LocalBasisType& localBasis () const { return *(finiteElement_.basis_); } /** \todo Please doc me ! */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return *(finiteElement_.coeff_); } /** \todo Please doc me ! */ const typename Traits::LocalInterpolationType& localInterpolation () const { return *(finiteElement_.interpol_); } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return finiteElement_.basis_->size(); } /** \todo Please doc me ! */ GeometryType type () const { return GeometryType(topologyId_,dimDomain); } /** \todo Please doc me ! */ unsigned int topologyId () const { return topologyId_; } private: struct FiniteElement { FiniteElement() : basis_(0), coeff_(0), interpol_(0) {} template void create( const Key &key ) { release(); basis_ = BasisF::template create(key); coeff_ = CoeffF::template create(key); interpol_ = InterpolF::template create(key); } void release() { if (basis_) BasisF::release(basis_); if (coeff_) CoeffF::release(coeff_); if (interpol_) InterpolF::release(interpol_); basis_=0; coeff_=0; interpol_=0; } template< class Topology > struct Maker { static void apply ( const Key &key, FiniteElement &finiteElement ) { finiteElement.template create(key); }; }; typename Traits::LocalBasisType *basis_; typename Traits::LocalCoefficientsType *coeff_; typename Traits::LocalInterpolationType *interpol_; }; unsigned int topologyId_; Key key_; FiniteElement finiteElement_; }; /** * @brief Takes the basis and interpolation factory from a given * LocalFiniteElement (derived from GenericLocalFiniteElement) * and replaces the coefficients with dg local keys, i.e., * attaches all degrees of freedom to the codimension zero entity. **/ template struct DGLocalFiniteElement : public GenericLocalFiniteElement< typename FE::BasisFactory, DGLocalCoefficientsFactory< typename FE::BasisFactory >, typename FE::InterpolationFactory> { typedef GenericLocalFiniteElement< typename FE::BasisFactory, DGLocalCoefficientsFactory< typename FE::BasisFactory >, typename FE::InterpolationFactory> Base; public: typedef typename Base::Traits Traits; /** \todo Please doc me ! */ DGLocalFiniteElement ( const GeometryType >, const typename Base::Key &key ) : Base( gt, key ) {} }; /** * @brief Takes the basis factory from a given * LocalFiniteElement (derived from GenericLocalFiniteElement) * and replaces the coefficients with dg local keys, i.e., * attaches all degrees of freedom to the codimension zero entity * and uses a l2 interpolation. **/ template struct L2LocalFiniteElement : public GenericLocalFiniteElement< typename FE::BasisFactory, DGLocalCoefficientsFactory< typename FE::BasisFactory >, LocalL2InterpolationFactory< typename FE::BasisFactory, false > > { typedef GenericLocalFiniteElement< typename FE::BasisFactory, DGLocalCoefficientsFactory< typename FE::BasisFactory >, LocalL2InterpolationFactory< typename FE::BasisFactory, false > > Base; public: typedef typename Base::Traits Traits; /** \todo Please doc me ! */ L2LocalFiniteElement ( const GeometryType >, const typename Base::Key &key ) : Base( gt, key ) {} }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/utility/monomialbasis.hh000066400000000000000000000676701313314431100263440ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_MONOMIALBASIS_HH #define DUNE_MONOMIALBASIS_HH #include #include #include #include #include #include #include #include namespace Dune { /************************************************ * Classes for evaluating ''Monomials'' on any order * for all reference element type. * For a simplex topology these are the nomral * monomials for cube topologies the bimonomials. * The construction follows the construction of the * generic geometries using tensor products for * prism generation and duffy transform for pyramid * construction. * A derivative argument can be applied, in which case * all derivatives up to the desired order are * evaluated. Note that in for higher order derivatives * only the ''lower'' part of the symmetric tensor * is evaluated, e.g., passing derivative equal to 2 * to the class will provide the vector * (d/dxdx p, d/dxydx p, d/dydy p, * d/dx p, d/dy p, p) * Important: * So far the computation of the derivatives has not * been fully implemented for general pyramid * construction, i.e., in the case where a pyramid is * build over a non simplex base geometry. * * Central classes: * 1) template< class Topology, class F > * class MonomialBasisImpl; * Implementation of the monomial evaluation for * a given topology and field type. * The method evaluate fills a F* vector * 2) template< class Topology, class F > * class MonomialBasis * The base class for the static monomial evaluation * providing addiional evaluate methods including * one taking std::vector. * 3) template< int dim, class F > * class VirtualMonomialBasis * Virtualization of the MonomialBasis. * 4) template< int dim, class F > * struct MonomialBasisFactory; * A factory class for the VirtualMonomialBasis * 5) template< int dim, class F > * struct MonomialBasisProvider * A singleton container for the virtual monomial * basis ************************************************/ // Internal Forward Declarations // ----------------------------- template< class Topology > class MonomialBasisSize; template< class Topology, class F > class MonomialBasis; // MonomialBasisSize // ----------------- template<> class MonomialBasisSize< Impl::Point > { typedef MonomialBasisSize< Impl::Point > This; public: static This &instance () { static This _instance; return _instance; } typedef Impl::Point Topology; friend class MonomialBasisSize< Impl::Prism< Topology > >; friend class MonomialBasisSize< Impl::Pyramid< Topology > >; mutable unsigned int maxOrder_; // sizes_[ k ]: number of basis functions of exactly order k mutable unsigned int *sizes_; // numBaseFunctions_[ k ] = sizes_[ 0 ] + ... + sizes_[ k ] mutable unsigned int *numBaseFunctions_; MonomialBasisSize () : maxOrder_( 0 ), sizes_( 0 ), numBaseFunctions_( 0 ) { computeSizes( 2 ); } ~MonomialBasisSize () { delete[] sizes_; delete[] numBaseFunctions_; } unsigned int operator() ( const unsigned int order ) const { return numBaseFunctions_[ order ]; } unsigned int maxOrder () const { return maxOrder_; } void computeSizes ( unsigned int order ) const { if (order <= maxOrder_) return; maxOrder_ = order; delete [] sizes_; delete [] numBaseFunctions_; sizes_ = new unsigned int [ order+1 ]; numBaseFunctions_ = new unsigned int [ order+1 ]; sizes_[ 0 ] = 1; numBaseFunctions_[ 0 ] = 1; for( unsigned int k = 1; k <= order; ++k ) { sizes_[ k ] = 0; numBaseFunctions_[ k ] = 1; } } }; template< class BaseTopology > class MonomialBasisSize< Impl::Prism< BaseTopology > > { typedef MonomialBasisSize< Impl::Prism< BaseTopology > > This; public: static This &instance () { static This _instance; return _instance; } typedef Impl::Prism< BaseTopology > Topology; friend class MonomialBasisSize< Impl::Prism< Topology > >; friend class MonomialBasisSize< Impl::Pyramid< Topology > >; mutable unsigned int maxOrder_; // sizes_[ k ]: number of basis functions of exactly order k mutable unsigned int *sizes_; // numBaseFunctions_[ k ] = sizes_[ 0 ] + ... + sizes_[ k ] mutable unsigned int *numBaseFunctions_; MonomialBasisSize () : maxOrder_( 0 ), sizes_( 0 ), numBaseFunctions_( 0 ) { computeSizes( 2 ); } ~MonomialBasisSize () { delete[] sizes_; delete[] numBaseFunctions_; } unsigned int operator() ( const unsigned int order ) const { return numBaseFunctions_[ order ]; } unsigned int maxOrder() const { return maxOrder_; } void computeSizes ( unsigned int order ) const { if (order <= maxOrder_) return; maxOrder_ = order; delete[] sizes_; delete[] numBaseFunctions_; sizes_ = new unsigned int[ order+1 ]; numBaseFunctions_ = new unsigned int[ order+1 ]; MonomialBasisSize &baseBasis = MonomialBasisSize::instance(); baseBasis.computeSizes( order ); const unsigned int *const baseSizes = baseBasis.sizes_; const unsigned int *const baseNBF = baseBasis.numBaseFunctions_; sizes_[ 0 ] = 1; numBaseFunctions_[ 0 ] = 1; for( unsigned int k = 1; k <= order; ++k ) { sizes_[ k ] = baseNBF[ k ] + k*baseSizes[ k ]; numBaseFunctions_[ k ] = numBaseFunctions_[ k-1 ] + sizes_[ k ]; } } }; template< class BaseTopology > class MonomialBasisSize< Impl::Pyramid< BaseTopology > > { typedef MonomialBasisSize< Impl::Pyramid< BaseTopology > > This; public: static This &instance () { static This _instance; return _instance; } typedef Impl::Pyramid< BaseTopology > Topology; friend class MonomialBasisSize< Impl::Prism< Topology > >; friend class MonomialBasisSize< Impl::Pyramid< Topology > >; mutable unsigned int maxOrder_; // sizes_[ k ]: number of basis functions of exactly order k mutable unsigned int *sizes_; // numBaseFunctions_[ k ] = sizes_[ 0 ] + ... + sizes_[ k ] mutable unsigned int *numBaseFunctions_; MonomialBasisSize () : maxOrder_( 0 ), sizes_( 0 ), numBaseFunctions_( 0 ) { computeSizes( 2 ); } ~MonomialBasisSize () { delete[] sizes_; delete[] numBaseFunctions_; } unsigned int operator() ( const unsigned int order ) const { return numBaseFunctions_[ order ]; } unsigned int maxOrder() const { return maxOrder_; } void computeSizes ( unsigned int order ) const { if (order <= maxOrder_) return; maxOrder_ = order; delete[] sizes_; delete[] numBaseFunctions_; sizes_ = new unsigned int[ order+1 ]; numBaseFunctions_ = new unsigned int[ order+1 ]; MonomialBasisSize &baseBasis = MonomialBasisSize::instance(); baseBasis.computeSizes( order ); const unsigned int *const baseNBF = baseBasis.numBaseFunctions_; sizes_[ 0 ] = 1; numBaseFunctions_[ 0 ] = 1; for( unsigned int k = 1; k <= order; ++k ) { sizes_[ k ] = baseNBF[ k ]; numBaseFunctions_[ k ] = numBaseFunctions_[ k-1 ] + sizes_[ k ]; } } }; // MonomialBasisHelper // ------------------- template< int mydim, int dim, class F > struct MonomialBasisHelper { typedef MonomialBasisSize< typename Impl::SimplexTopology< mydim >::type > MySize; typedef MonomialBasisSize< typename Impl::SimplexTopology< dim >::type > Size; static void copy ( const unsigned int deriv, F *&wit, F *&rit, const unsigned int numBaseFunctions, const F &z ) { // n(d,k) = size[d]; MySize &mySize = MySize::instance(); Size &size = Size::instance(); const F *const rend = rit + size( deriv )*numBaseFunctions; for( ; rit != rend; ) { F *prit = rit; *wit = z * *rit; ++rit, ++wit; for( unsigned d = 1; d <= deriv; ++d ) { #ifndef NDEBUG const F *const derivEnd = rit + mySize.sizes_[ d ]; #endif { const F *const drend = rit + mySize.sizes_[ d ] - mySize.sizes_[ d-1 ]; for( ; rit != drend ; ++rit, ++wit ) *wit = z * *rit; } for (unsigned int j=1; j(); } } } }; // MonomialBasisImpl // ----------------- template< class Topology, class F > class MonomialBasisImpl; template< class F > class MonomialBasisImpl< Impl::Point, F > { typedef MonomialBasisImpl< Impl::Point, F > This; public: typedef Impl::Point Topology; typedef F Field; static const unsigned int dimDomain = Topology::dimension; typedef FieldVector< Field, dimDomain > DomainVector; private: friend class MonomialBasis< Topology, Field >; friend class MonomialBasisImpl< Impl::Prism< Topology >, Field >; friend class MonomialBasisImpl< Impl::Pyramid< Topology >, Field >; template< int dimD > void evaluate ( const unsigned int deriv, const unsigned int order, const FieldVector< Field, dimD > &x, const unsigned int block, const unsigned int *const offsets, Field *const values ) const { *values = Unity< F >(); F *const end = values + block; for( Field *it = values+1 ; it != end; ++it ) *it = Zero< F >(); } void integrate ( const unsigned int order, const unsigned int *const offsets, Field *const values ) const { values[ 0 ] = Unity< Field >(); } }; template< class BaseTopology, class F > class MonomialBasisImpl< Impl::Prism< BaseTopology >, F > { typedef MonomialBasisImpl< Impl::Prism< BaseTopology >, F > This; public: typedef Impl::Prism< BaseTopology > Topology; typedef F Field; static const unsigned int dimDomain = Topology::dimension; typedef FieldVector< Field, dimDomain > DomainVector; private: friend class MonomialBasis< Topology, Field >; friend class MonomialBasisImpl< Impl::Prism< Topology >, Field >; friend class MonomialBasisImpl< Impl::Pyramid< Topology >, Field >; typedef MonomialBasisSize< BaseTopology > BaseSize; typedef MonomialBasisSize< Topology > Size; MonomialBasisImpl< BaseTopology, Field > baseBasis_; MonomialBasisImpl () {} template< int dimD > void evaluate ( const unsigned int deriv, const unsigned int order, const FieldVector< Field, dimD > &x, const unsigned int block, const unsigned int *const offsets, Field *const values ) const { typedef MonomialBasisHelper< dimDomain, dimD, Field > Helper; const BaseSize &size = BaseSize::instance(); const Field &z = x[ dimDomain-1 ]; // fill first column baseBasis_.evaluate( deriv, order, x, block, offsets, values ); Field *row0 = values; for( unsigned int k = 1; k <= order; ++k ) { Field *row1 = values + block*offsets[ k-1 ]; Field *wit = row1 + block*size.sizes_[ k ]; Helper::copy( deriv, wit, row1, k*size.sizes_[ k ], z ); Helper::copy( deriv, wit, row0, size( k-1 ), z ); row0 = row1; } } void integrate ( const unsigned int order, const unsigned int *const offsets, Field *const values ) const { const BaseSize &size = BaseSize::instance(); const Size &mySize = Size::instance(); // fill first column baseBasis_.integrate( order, offsets, values ); const unsigned int *const baseSizes = size.sizes_; Field *row0 = values; for( unsigned int k = 1; k <= order; ++k ) { Field *const row1begin = values + offsets[ k-1 ]; Field *const row1End = row1begin + mySize.sizes_[ k ]; assert( (unsigned int)(row1End - values) <= offsets[ k ] ); Field *row1 = row1begin; Field *it = row1begin + baseSizes[ k ]; for( unsigned int j = 1; j <= k; ++j ) { Field *const end = it + baseSizes[ k ]; assert( (unsigned int)(end - values) <= offsets[ k ] ); for( ; it != end; ++row1, ++it ) *it = (Field( j ) / Field( j+1 )) * (*row1); } for( ; it != row1End; ++row0, ++it ) *it = (Field( k ) / Field( k+1 )) * (*row0); row0 = row1; } } }; template< class BaseTopology, class F > class MonomialBasisImpl< Impl::Pyramid< BaseTopology >, F > { typedef MonomialBasisImpl< Impl::Pyramid< BaseTopology >, F > This; public: typedef Impl::Pyramid< BaseTopology > Topology; typedef F Field; static const unsigned int dimDomain = Topology::dimension; typedef FieldVector< Field, dimDomain > DomainVector; private: friend class MonomialBasis< Topology, Field >; friend class MonomialBasisImpl< Impl::Prism< Topology >, Field >; friend class MonomialBasisImpl< Impl::Pyramid< Topology >, Field >; typedef MonomialBasisSize< BaseTopology > BaseSize; typedef MonomialBasisSize< Topology > Size; MonomialBasisImpl< BaseTopology, Field > baseBasis_; MonomialBasisImpl () {} template< int dimD > void evaluateSimplexBase ( const unsigned int deriv, const unsigned int order, const FieldVector< Field, dimD > &x, const unsigned int block, const unsigned int *const offsets, Field *const values, const BaseSize &size ) const { baseBasis_.evaluate( deriv, order, x, block, offsets, values ); } template< int dimD > void evaluatePyramidBase ( const unsigned int deriv, const unsigned int order, const FieldVector< Field, dimD > &x, const unsigned int block, const unsigned int *const offsets, Field *const values, const BaseSize &size ) const { Field omz = Unity< Field >() - x[ dimDomain-1 ]; if( Zero< Field >() < omz ) { const Field invomz = Unity< Field >() / omz; FieldVector< Field, dimD > y; for( unsigned int i = 0; i < dimDomain-1; ++i ) y[ i ] = x[ i ] * invomz; // fill first column baseBasis_.evaluate( deriv, order, y, block, offsets, values ); Field omzk = omz; for( unsigned int k = 1; k <= order; ++k ) { Field *it = values + block*offsets[ k-1 ]; Field *const end = it + block*size.sizes_[ k ]; for( ; it != end; ++it ) *it *= omzk; omzk *= omz; } } else { assert( deriv==0 ); *values = Unity< Field >(); for( unsigned int k = 1; k <= order; ++k ) { Field *it = values + block*offsets[ k-1 ]; Field *const end = it + block*size.sizes_[ k ]; for( ; it != end; ++it ) *it = Zero< Field >(); } } } template< int dimD > void evaluate ( const unsigned int deriv, const unsigned int order, const FieldVector< Field, dimD > &x, const unsigned int block, const unsigned int *const offsets, Field *const values ) const { typedef MonomialBasisHelper< dimDomain, dimD, Field > Helper; const BaseSize &size = BaseSize::instance(); if( Impl::IsSimplex< Topology >::value ) evaluateSimplexBase( deriv, order, x, block, offsets, values, size ); else evaluatePyramidBase( deriv, order, x, block, offsets, values, size ); Field *row0 = values; for( unsigned int k = 1; k <= order; ++k ) { Field *row1 = values + block*offsets[ k-1 ]; Field *wit = row1 + block*size.sizes_[ k ]; Helper::copy( deriv, wit, row0, size( k-1 ), x[ dimDomain-1 ] ); row0 = row1; } } void integrate ( const unsigned int order, const unsigned int *const offsets, Field *const values ) const { const BaseSize &size = BaseSize::instance(); // fill first column baseBasis_.integrate( order, offsets, values ); const unsigned int *const baseSizes = size.sizes_; { Field *const col0End = values + baseSizes[ 0 ]; for( Field *it = values; it != col0End; ++it ) *it *= Field( 1 ) / Field( int(dimDomain) ); } Field *row0 = values; for( unsigned int k = 1; k <= order; ++k ) { const Field factor = (Field( 1 ) / Field( k + dimDomain )); Field *const row1 = values+offsets[ k-1 ]; Field *const col0End = row1 + baseSizes[ k ]; Field *it = row1; for( ; it != col0End; ++it ) *it *= factor; for( unsigned int i = 1; i <= k; ++i ) { Field *const end = it + baseSizes[ k-i ]; assert( (unsigned int)(end - values) <= offsets[ k ] ); for( ; it != end; ++row0, ++it ) *it = (*row0) * (Field( i ) * factor); } row0 = row1; } } }; // MonomialBasis // ------------- template< class Topology, class F > class MonomialBasis : public MonomialBasisImpl< Topology, F > { typedef MonomialBasis< Topology, F > This; typedef MonomialBasisImpl< Topology, F > Base; public: static const unsigned int dimension = Base::dimDomain; static const unsigned int dimRange = 1; typedef typename Base::Field Field; typedef typename Base::DomainVector DomainVector; typedef Dune::FieldVector RangeVector; typedef MonomialBasisSize Size; MonomialBasis (unsigned int order) : Base(), order_(order), size_(Size::instance()) { assert(order<=1024); // avoid wrapping of unsigned int (0-1) order=1024 is quite hight...) } const unsigned int *sizes ( unsigned int order ) const { size_.computeSizes( order ); return size_.numBaseFunctions_; } const unsigned int *sizes () const { return sizes( order_ ); } unsigned int size () const { size_.computeSizes( order_ ); return size_( order_ ); } unsigned int derivSize ( const unsigned int deriv ) const { typedef typename Impl::SimplexTopology< dimension >::type SimplexTopology; MonomialBasisSize< SimplexTopology >::instance().computeSizes( deriv ); return MonomialBasisSize< SimplexTopology >::instance() ( deriv ); } unsigned int order () const { return order_ ; } unsigned int topologyId ( ) const { return Topology::id; } void evaluate ( const unsigned int deriv, const DomainVector &x, Field *const values ) const { Base::evaluate( deriv, order_, x, derivSize( deriv ), sizes( order_ ), values ); } template void evaluate ( const DomainVector &x, Field *const values ) const { evaluate( deriv, x, values ); } template void evaluate ( const DomainVector &x, Vector &values ) const { evaluate(x,&(values[0])); } template void evaluate ( const DomainVector &x, Derivatives *values ) const { evaluate(x,&(values->block())); } template< unsigned int deriv > void evaluate ( const DomainVector &x, FieldVector::size> *values ) const { evaluate(0,x,&(values[0][0])); } template void evaluate ( const DomainVector &x, Vector &values ) const { evaluate<0>(x,&(values[0])); } template< class DVector, class RVector > void evaluate ( const DVector &x, RVector &values ) const { assert( DVector::dimension == dimension); DomainVector bx; for( int d = 0; d < dimension; ++d ) field_cast( x[ d ], bx[ d ] ); evaluate<0>( bx, values ); } void integrate ( Field *const values ) const { Base::integrate( order_, sizes( order_ ), values ); } template void integrate ( Vector &values ) const { integrate( &(values[ 0 ]) ); } private: MonomialBasis(const This&); This& operator=(const This&); unsigned int order_; Size &size_; }; // StdMonomialBasis // ---------------- template< int dim,class F > class StandardMonomialBasis : public MonomialBasis< typename Impl::SimplexTopology< dim >::type, F > { typedef StandardMonomialBasis< dim, F > This; typedef MonomialBasis< typename Impl::SimplexTopology< dim >::type, F > Base; public: typedef typename Impl::SimplexTopology< dim >::type Topology; static const int dimension = dim; StandardMonomialBasis ( unsigned int order ) : Base( order ) {} }; // StandardBiMonomialBasis // ----------------------- template< int dim, class F > class StandardBiMonomialBasis : public MonomialBasis< typename Impl::CubeTopology< dim >::type, F > { typedef StandardBiMonomialBasis< dim, F > This; typedef MonomialBasis< typename Impl::CubeTopology< dim >::type, F > Base; public: typedef typename Impl::CubeTopology< dim >::type Topology; static const int dimension = dim; StandardBiMonomialBasis ( unsigned int order ) : Base( order ) {} }; // ----------------------------------------------------------- // ----------------------------------------------------------- // VirtualMonomialBasis // ------------------- template< int dim, class F > class VirtualMonomialBasis { typedef VirtualMonomialBasis< dim, F > This; public: typedef F Field; typedef F StorageField; static const int dimension = dim; static const unsigned int dimRange = 1; typedef FieldVector DomainVector; typedef FieldVector RangeVector; explicit VirtualMonomialBasis(unsigned int topologyId, unsigned int order) : order_(order), topologyId_(topologyId) {} virtual ~VirtualMonomialBasis() {} virtual const unsigned int *sizes ( ) const = 0; unsigned int size ( ) const { return sizes( )[ order_ ]; } unsigned int order () const { return order_; } unsigned int topologyId ( ) const { return topologyId_; } virtual void evaluate ( const unsigned int deriv, const DomainVector &x, Field *const values ) const = 0; template < unsigned int deriv > void evaluate ( const DomainVector &x, Field *const values ) const { evaluate( deriv, x, values ); } template < unsigned int deriv, int size > void evaluate ( const DomainVector &x, Dune::FieldVector *const values ) const { evaluate( deriv, x, &(values[0][0]) ); } template void evaluate ( const DomainVector &x, Derivatives *values ) const { evaluate(x,&(values->block())); } template void evaluate ( const DomainVector &x, Vector &values ) const { evaluate( x, &(values[ 0 ]) ); } template< class Vector > void evaluate ( const DomainVector &x, Vector &values ) const { evaluate<0>(x,values); } template< class DVector, class RVector > void evaluate ( const DVector &x, RVector &values ) const { assert( DVector::dimension == dimension); DomainVector bx; for( int d = 0; d < dimension; ++d ) field_cast( x[ d ], bx[ d ] ); evaluate<0>( bx, values ); } template< unsigned int deriv, class DVector, class RVector > void evaluate ( const DVector &x, RVector &values ) const { assert( DVector::dimension == dimension); DomainVector bx; for( int d = 0; d < dimension; ++d ) field_cast( x[ d ], bx[ d ] ); evaluate( bx, values ); } virtual void integrate ( Field *const values ) const = 0; template void integrate ( Vector &values ) const { integrate( &(values[ 0 ]) ); } protected: unsigned int order_; unsigned int topologyId_; }; template< class Topology, class F > class VirtualMonomialBasisImpl : public VirtualMonomialBasis< Topology::dimension, F > { typedef VirtualMonomialBasis< Topology::dimension, F > Base; typedef VirtualMonomialBasisImpl< Topology, F > This; public: typedef typename Base::Field Field; typedef typename Base::DomainVector DomainVector; VirtualMonomialBasisImpl(unsigned int order) : Base(Topology::id,order), basis_(order) {} const unsigned int *sizes ( ) const { return basis_.sizes(order_); } void evaluate ( const unsigned int deriv, const DomainVector &x, Field *const values ) const { basis_.evaluate(deriv,x,values); } void integrate ( Field *const values ) const { basis_.integrate(values); } private: MonomialBasis basis_; using Base::order_; }; // MonomialBasisFactory // -------------------- template< int dim, class F > struct MonomialBasisFactory; template< int dim, class F > struct MonomialBasisFactoryTraits { static const unsigned int dimension = dim; typedef unsigned int Key; typedef const VirtualMonomialBasis< dimension, F > Object; typedef MonomialBasisFactory Factory; }; template< int dim, class F > struct MonomialBasisFactory : public TopologyFactory< MonomialBasisFactoryTraits > { static const unsigned int dimension = dim; typedef F StorageField; typedef MonomialBasisFactoryTraits Traits; typedef typename Traits::Key Key; typedef typename Traits::Object Object; template < int dd, class FF > struct EvaluationBasisFactory { typedef MonomialBasisFactory Type; }; template< class Topology > static Object* createObject ( const Key &order ) { return new VirtualMonomialBasisImpl< Topology, StorageField >( order ); } }; // MonomialBasisProvider // --------------------- template< int dim, class SF > struct MonomialBasisProvider : public TopologySingletonFactory< MonomialBasisFactory< dim, SF > > { static const unsigned int dimension = dim; typedef SF StorageField; template < int dd, class FF > struct EvaluationBasisFactory { typedef MonomialBasisProvider Type; }; }; } #endif dune-localfunctions-2.5.1/dune/localfunctions/utility/multiindex.hh000066400000000000000000000257251313314431100256640ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_MULTIINDEX_HH #define DUNE_MULTIINDEX_HH #include #include #include #include namespace Dune { /**************************************************************** * Provide a Field class which can be used in evaluation methods * to produce MultiIndex presentation of polynomials. ****************************************************************/ // Internal Forward Declarations // ----------------------------- template< int dim, class Field > class MultiIndex; template< int dim, class Field > std::ostream &operator<< ( std::ostream &, const MultiIndex< dim,Field > & ); // MultiIndex // ---------- template< int dim,class Field > class MultiIndex { typedef MultiIndex< dim, Field > This; friend std::ostream &operator<<<> ( std::ostream &, const This & ); public: static const int dimension = dim; MultiIndex () : vecZ_( 0 ), vecOMZ_( 0 ), factor_( 1. ), next_( 0 ) {} template explicit MultiIndex (const F &f) : vecZ_( 0 ), vecOMZ_( 0 ), factor_( field_cast(f) ), next_( 0 ) {} MultiIndex ( int, const This &other ) : vecZ_( other.vecOMZ_ ), vecOMZ_( other.vecZ_ ), factor_( other.factor_ ) { assert(!other.next_); if (other.next_) { next_ = new This( *(other.next_) ); } else next_ = 0; } MultiIndex ( const This &other ) : vecZ_( other.vecZ_ ), vecOMZ_( other.vecOMZ_ ), factor_( other.factor_ ) { if (other.next_) { next_ = new This( *(other.next_) ); } else next_ = 0; } ~MultiIndex() { remove(); } int z(int i) const { return vecZ_[i]; } int omz(int i) const { return vecOMZ_[i]; } const Field &factor() const { return factor_; } This &operator= ( const This &other ) { remove(); vecZ_ = other.vecZ_; vecOMZ_ = other.vecOMZ_; factor_ = other.factor_; if (other.next_) next_ = new This(*(other.next_)); return *this; } This &operator= ( const Zero &f ) { remove(); vecZ_ = 0; vecOMZ_ = 0; factor_ = 0.; return *this; } This &operator= ( const Unity &f ) { remove(); vecZ_ = 0; vecOMZ_ = 0; factor_ = 1.; return *this; } template This &operator= ( const F &f ) { remove(); vecZ_ = 0; vecOMZ_ = 0; factor_ = field_cast(f); return *this; } bool operator== (const This &other) const { assert(!next_ && !other.next_); return (vecZ_==other.vecZ_ && vecOMZ_==other.vecOMZ_ && factor_==other.factor_); } template This &operator*= ( const F &f ) { factor_ *= field_cast(f); if (next_) (*next_) *= f; return *this; } template This &operator/= ( const F &f ) { factor_ /= field_cast(f); if (next_) (*next_) /= f; return *this; } This &operator*= ( const This &other ) { assert(!other.next_); vecZ_ += other.vecZ_; vecOMZ_ += other.vecOMZ_; factor_ *= other.factor_; if (next_) (*next_) *= other; return *this; } This &operator/= ( const This &other ) { assert(!other.next_); vecZ_ -= other.vecZ_; vecOMZ_ -= other.vecOMZ_; factor_ /= other.factor_; if (next_) (*next_) /= other; return *this; } This &operator+= ( const This &other ) { assert(!other.next_); if (std::abs(other.factor_)<1e-10) return *this; if (std::abs(factor_)<1e-10) { *this = other; return *this; } if (!sameMultiIndex(other)) { if (next_) (*next_)+=other; else { next_ = new This(other); } } else factor_ += other.factor_; return *this; } This &operator-= ( const This &other ) { assert(!other.next_); if (!sameMultiIndex(other)) { if (next_) next_-=other; else { next_ = new This(other); } } else factor_ -= other.factor_; return *this; } template This operator* ( const F &f ) const { This z = *this; return (z *= f); } template This operator/ ( const F &f ) const { This z = *this; return (z /= f); } This operator* ( const This &other ) const { This z = *this; return (z *= other); } This operator/ ( const This &other ) const { This z = *this; return (z /= other); } This operator+ ( const This &other ) const { This z = *this; return (z += other); } This operator- ( const This &other ) const { This z = *this; return (z -= other); } void set ( int d, int power = 1 ) { vecZ_[ d ] = power; } int absZ () const { int ret = 0; for( int i = 0; i < dimension; ++i ) ret += std::abs( vecZ_[ i ] ); return ret; } int absOMZ() const { int ret = 0; for( int i = 0; i < dimension; ++i ) ret += std::abs( vecOMZ_[ i ] ); return ret; } bool sameMultiIndex(const This &ind) { for( int i = 0; i < dimension; ++i ) { if ( vecZ_[i] != ind.vecZ_[i] || vecOMZ_[i] != vecOMZ_[i] ) return false; } return true; } private: void remove() { if (next_) { next_->remove(); delete next_; next_ = 0; } } typedef Dune::FieldVector< int, dimension > Vector; Vector vecZ_; Vector vecOMZ_; Field factor_; This *next_; }; template MultiIndex operator* ( const F &f, const MultiIndex &m) { MultiIndex z = m; return (z *= f); } template MultiIndex operator/ ( const F &f, const MultiIndex &m) { MultiIndex z = m; return (z /= f); } template std::ostream &operator<<(std::ostream& out,const std::vector >& y) { for (unsigned int r=0; r std::ostream &operator<<(std::ostream& out, const std::vector,dimR1,dimR2> >& y) { out << "\\begin{eqnarray*}" << std::endl; for (unsigned int k=0; k std::ostream &operator<<(std::ostream& out,const MultiIndex& val) { bool first = true; const MultiIndex *m = &val; do { if (m->absZ()==0 && std::abs(m->factor())<1e-10) { if (!m->next_ || !first) { out << "0"; break; } else { m = m->next_; continue; } } if (m->factor()>0 && !first) out << " + "; else if (m->factor()<0) if (!first) out << " - "; else out << "- "; else out << " "; first = false; F f = std::abs(m->factor()); if (m->absZ()==0) out << f; else { if ( std::abs(f)<1e-10) out << 0; else { F f_1(f); f_1 -= 1.; // better Unity(); if ( std::abs(f_1)>1e-10) out << f; int absVal = 0; for (int i=0; ivecZ_[i]==0) continue; else if (m->vecZ_[i]==1) out << char('a'+i); else if (m->vecZ_[i]>0) out << char('a'+i) << "^" << m->vecZ_[i] << ""; else if (m->vecZ_[i]<0) out << char('a'+i) << "^" << m->vecZ_[i] << ""; absVal += m->vecZ_[i]; if (absValabsZ()) out << ""; } } } /* if (mi.absOMZ()>0) { for (int i=0;i<=mi.absZ();++i) { if (mi.vecOMZ_[i]==0) continue; else if (mi.vecOMZ_[i]==1) out << (1-char('a'+i)); else if (mi.vecOMZ_[i]>0) out << (1-char('a'+i)) << "^" << mi.vecOMZ_[i]; else if (mi.vecOMZ_[i]<0) out << (1-char('a'+i)) << "^" << mi.vecOMZ_[i]; if (i==mi.absZ()+1) out << "*"; } } */ m = m->next_; } while (m); return out; } template< int dim, class F> struct Unity< MultiIndex< dim, F > > { typedef MultiIndex< dim, F > Field; operator Field () const { return Field(); } Field operator- ( const Field &other ) const { return Field( 1, other ); } Field operator/ ( const Field &other ) const { return Field() / other; } }; template< int dim, class F > struct Zero< MultiIndex< dim,F > > { typedef MultiIndex< dim,F > Field; // zero does not acutally exist operator Field () { return Field(0); } }; template< int dim, class Field > bool operator< ( const Zero< MultiIndex< dim,Field > > &, const MultiIndex< dim,Field > & ) { return true; } template< int dim, class Field > bool operator< ( const MultiIndex< dim, Field > &f, const Zero< MultiIndex< dim,Field > > & ) { return true; } } #endif // #ifndef DUNE_MULTIINDEX_HH dune-localfunctions-2.5.1/dune/localfunctions/utility/polynomialbasis.hh000066400000000000000000000236531313314431100267050ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_POLYNOMIALBASIS_HH #define DUNE_POLYNOMIALBASIS_HH #include #include #include #include #include #include #include #include namespace Dune { // PolynomialBasis // --------------- /** * This is the basis class for a ''polynomial'' * basis, i.e., a basis consisting of linear * combiniations of a underlying second basis set. * Examples are standard polynomials where the * underlying basis is given by the MonomialBasis * class. The basis evaluation is given by the matrix * vector multiplication between the coefficient * matrix and the vector filled by evaluating the * underlying basis set. * This class is constructed using a reference of * the underlying basis and the coefficient matrix. * A specialization holding an instance * of the coefficient matrix is provided by the class * template< class Eval, class CM = SparseCoeffMatrix > * class PolynomialBasisWithMatrix; * * \tparam B Basis set with * static const int dimension -> dimension of reference element * typedef DomainVector -> coordinates in reference element * int size(int order) const -> number of basis functions * void evaluate( order, x, val ) const * int order * DomainVector x * Container val * \tparam CM stroage for coefficience with * typedef Field -> field of coefficience * static const int dimRange -> coeficience are of type * FieldMatrix * void mult( val, y ) * Container val * std::vector y * \tparam Container access to basis functions through forward iterator * typedef value_type * typedef const_iterator * const_iterator begin() **/ template< class Eval, class CM, class D=double, class R=double > class PolynomialBasis { typedef PolynomialBasis< Eval, CM > This; typedef Eval Evaluator; public: typedef CM CoefficientMatrix; typedef typename CoefficientMatrix::Field StorageField; static const unsigned int dimension = Evaluator::dimension; static const unsigned int dimRange = Evaluator::dimRange*CoefficientMatrix::blockSize; typedef LocalBasisTraits, R,dimRange,FieldVector, FieldMatrix > Traits; typedef typename Evaluator::Basis Basis; typedef typename Evaluator::DomainVector DomainVector; PolynomialBasis (const Basis &basis, const CoefficientMatrix &coeffMatrix, unsigned int size) : basis_(basis), coeffMatrix_(&coeffMatrix), eval_(basis), order_(basis.order()), size_(size) { // assert(coeffMatrix_); // assert(size_ <= coeffMatrix.size()); // !!! } const Basis &basis () const { return basis_; } const CoefficientMatrix &matrix () const { return *coeffMatrix_; } unsigned int order () const { return order_; } unsigned int size () const { return size_; } //! \brief Evaluate all shape functions void evaluateFunction (const typename Traits::DomainType& x, std::vector& out) const { out.resize(size()); evaluate(x,out); } //! \brief Evaluate Jacobian of all shape functions void evaluateJacobian (const typename Traits::DomainType& x, // position std::vector& out) const // return value { out.resize(size()); jacobian(x,out); } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainType& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } template< unsigned int deriv, class F > void evaluate ( const DomainVector &x, F *values ) const { coeffMatrix_->mult( eval_.template evaluate( x ), size(), values); } template< unsigned int deriv, class DVector, class F > void evaluate ( const DVector &x, F *values ) const { assert( DVector::dimension == dimension); DomainVector bx; for( int d = 0; d < dimension; ++d ) field_cast( x[ d ], bx[ d ] ); evaluate( bx, values ); } template struct Convert { static DomainVector apply( const DVector &x ) { assert( DVector::dimension == dimension); DomainVector bx; for( unsigned int d = 0; d < dimension; ++d ) field_cast( x[ d ], bx[ d ] ); return bx; } }; template struct Convert { static const DomainVector &apply( const DomainVector &x ) { return x; } }; template< unsigned int deriv, class DVector, class RVector > void evaluate ( const DVector &x, RVector &values ) const { assert(values.size()>=size()); const DomainVector &bx = Convert::apply(x); coeffMatrix_->mult( eval_.template evaluate( bx ), values ); } template void evaluate ( const DomainVector &x, std::vector > &values ) const { evaluate<0>(x,values); } template< class DVector, class RVector > void evaluate ( const DVector &x, RVector &values ) const { assert( DVector::dimension == dimension); DomainVector bx; for( unsigned int d = 0; d < dimension; ++d ) field_cast( x[ d ], bx[ d ] ); evaluate<0>( bx, values ); } template< unsigned int deriv, class Vector > void evaluateSingle ( const DomainVector &x, Vector &values ) const { assert(values.size()>=size()); coeffMatrix_->template mult( eval_.template evaluate( x ), values ); } template< unsigned int deriv, class Fy > void evaluateSingle ( const DomainVector &x, std::vector< FieldVector::size>,dimRange> > &values) const { evaluateSingle(x,reinterpret_cast::size*dimRange> >&>(values)); } template< unsigned int deriv, class Fy > void evaluateSingle ( const DomainVector &x, std::vector< FieldVector,dimRange> > &values) const { evaluateSingle(x,reinterpret_cast::size*dimRange> >&>(values)); } template void jacobian ( const DomainVector &x, std::vector > &values ) const { assert(values.size()>=size()); evaluateSingle<1>(x,reinterpret_cast >&>(values)); } template< class DVector, class RVector > void jacobian ( const DVector &x, RVector &values ) const { assert( DVector::dimension == dimension); DomainVector bx; for( unsigned int d = 0; d < dimension; ++d ) field_cast( x[ d ], bx[ d ] ); jacobian( bx, values ); } template void integrate ( std::vector &values ) const { assert(values.size()>=size()); coeffMatrix_->mult( eval_.template integrate(), values ); } protected: PolynomialBasis(const PolynomialBasis &other) : basis_(other.basis_), coeffMatrix_(other.coeffMatrix_), eval_(basis_), order_(basis_.order()), size_(other.size_) {} PolynomialBasis &operator=(const PolynomialBasis&); const Basis &basis_; const CoefficientMatrix* coeffMatrix_; mutable Evaluator eval_; unsigned int order_,size_; }; /** * Specialized version of PolynomialBasis with FieldMatrix for matrix * coefficience and std::vector for container type with FieldVector as * value type. This class stores the coefficient matrix with can be * constructed via the fill method */ template< class Eval, class CM = SparseCoeffMatrix, class D=double, class R=double> class PolynomialBasisWithMatrix : public PolynomialBasis< Eval, CM, D, R > { public: typedef CM CoefficientMatrix; private: typedef Eval Evaluator; typedef PolynomialBasisWithMatrix< Evaluator, CM > This; typedef PolynomialBasis Base; public: typedef typename Base::Basis Basis; PolynomialBasisWithMatrix (const Basis &basis) : Base(basis,coeffMatrix_,0) {} template void fill(const Matrix& matrix) { coeffMatrix_.fill(matrix); this->size_ = coeffMatrix_.size(); } template void fill(const Matrix& matrix,int size) { coeffMatrix_.fill(matrix); assert(size<=coeffMatrix_.size()); this->size_ = size; } private: PolynomialBasisWithMatrix(const PolynomialBasisWithMatrix &); PolynomialBasisWithMatrix &operator=(const PolynomialBasisWithMatrix &); CoefficientMatrix coeffMatrix_; }; } #endif // DUNE_POLYNOMIALBASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/utility/tensor.hh000066400000000000000000000661161313314431100250130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TENSOR_HH #define DUNE_TENSOR_HH #include #include #include #include namespace Dune { /*********************************************** * The classes here are work in progress. * Basically they provide tensor structures for * higher order derivatives of vector valued function. * Two storage structures are provided * (either based on the components of the vector valued * functions or on the order of the derivative). * Conversions are supplied between the two storage * structures and simple operations, which make the * code difficult to use and requires rewritting... ***************************************************/ // Structure for scalar tensor of order deriv template class LFETensor { typedef LFETensor This; typedef LFETensor BaseDim; typedef LFETensor BaseDeriv; public: typedef F field_type; static const unsigned int size = BaseDim::size+BaseDeriv::size; typedef Dune::FieldVector Block; template< class FF > This &operator= ( const FF &f ) { block() = field_cast< F >( f ); return *this; } This &operator= ( const Block &b ) { block() = b; return *this; } This &operator*= ( const field_type &f ) { block() *= f; return *this; } const field_type &operator[] ( const unsigned int i ) const { return block()[ i ]; } field_type &operator[] ( const unsigned int i ) { return block()[ i ]; } Block &block() { return block_; } const Block &block() const { return block_; } void axpy(const F& a, const This &y) { block().axpy(a,y.block()); } template void assign(const LFETensor &y) { field_cast(y.block(),block()); } Block block_; }; // ****************************************** template struct LFETensor { static const int size = 0; }; template struct LFETensor { static const int size = 1; }; template class LFETensor { typedef LFETensor This; public: typedef F field_type; static const int size = 1; typedef Dune::FieldVector Block; template< class FF > This &operator= ( const FF &f ) { block() = field_cast< F >( f ); return *this; } This &operator= ( const Block &b ) { block() = b; return *this; } This &operator*= ( const field_type &f ) { block() *= f; return *this; } const F &operator[] ( const unsigned int i ) const { return block()[ i ]; } F &operator[] ( const unsigned int i ) { return block()[ i ]; } void axpy(const F& a, const This &y) { block().axpy(a,y.block()); } template void assign(const LFETensor &y) { field_cast(y.block(),block()); } Block &block() { return block_; } const Block &block() const { return block_; } Block block_; }; // *********************************************************** // Structure for all derivatives up to order deriv // for vector valued function enum DerivativeLayout {value,derivative}; template struct Derivatives; // Implemnetation for valued based layout template struct Derivatives : public Derivatives { typedef Derivatives This; typedef Derivatives Base; typedef LFETensor ThisLFETensor; typedef F Field; typedef F field_type; static const DerivativeLayout layout = value; static const unsigned int dimDomain = dimD; static const unsigned int dimRange = dimR; // size needs to be an anonymous enum value for gcc 3.4 compatibility enum { size = Base::size+ThisLFETensor::size*dimR }; typedef Dune::FieldVector Block; This &operator=(const F& f) { block() = f; return *this; } This &operator=(const Dune::FieldVector &t) { tensor_ = t; return *this; } template This &operator=(const Dune::FieldVector,dimR> &t) { tensor() = t; return *this; } This &operator=(const Block &t) { block() = t; return *this; } This &operator*= ( const field_type &f ) { block() *= f; return *this; } void axpy(const F &a, const This &y) { block().axpy(a,y.block()); } // assign with same layout (only different Field) template void assign(const Derivatives &y) { field_cast(y.block(),block()); } // assign with different layout (same dimRange) template void assign(const Derivatives &y) { Base::assign(y); for (int rr=0; rr()[0]; } // assign with rth component of function template void assign(const Derivatives &y,unsigned int r) { assign(y.block(),r); } // assign with scalar functions to component r template void assign(unsigned int r,const Derivatives &y) { assign(r,y.block()); } template void assign(unsigned int r,const Derivatives &y) { assign(r,y[0]); } Block &block() { return reinterpret_cast(*this); } const Block &block() const { return reinterpret_cast(*this); } template const Dune::FieldVector,dimR> &tensor() const { // use integral_constant here to stay compatible with Int2Type const std::integral_constant a = {}; return tensor(a); } template Dune::FieldVector,dimR> &tensor() { // use integral_constant here to stay compatible with Int2Type return tensor(std::integral_constant()); } template const Dune::FieldVector::size*dimR> &block() const { // use integral_constant here to stay compatible with Int2Type const std::integral_constant a = {}; return reinterpret_cast::size*dimR>&>(tensor(a)); } template Dune::FieldVector::size*dimR> &block() { // use integral_constant here to stay compatible with Int2Type const std::integral_constant a = {}; return reinterpret_cast::size*dimR>&>(tensor(a)); } ThisLFETensor &operator[](int r) { return tensor_[r]; } const ThisLFETensor &operator[](int r) const { return tensor_[r]; } protected: template void assign(const FieldVector &y,unsigned int r) { Base::template assign(reinterpret_cast&>(y),r); tensor_[0] = reinterpret_cast&>(y[Base::size*dimRy+r*ThisLFETensor::size]); } template void assign(unsigned int r,const FieldVector &y) { Base::assign(r,reinterpret_cast&>(y)); tensor_[r] = reinterpret_cast&>(y[Base::size/dimR]); } // assign with different layout (same dimRange) template void assign(const Derivatives &y) { Base::assign(y); for (int rr=0; rr()[0]; } template const Dune::FieldVector,dimR> & tensor(const std::integral_constant &dorderVar) const { return Base::tensor(dorderVar); } const Dune::FieldVector,dimR> & tensor(const std::integral_constant &dorderVar) const { return tensor_; } template Dune::FieldVector,dimR> & tensor(const std::integral_constant &dorderVar) { return Base::tensor(dorderVar); } Dune::FieldVector,dimR> & tensor(const std::integral_constant &dorderVar) { return tensor_; } Dune::FieldVector tensor_; }; template struct Derivatives { typedef Derivatives This; typedef LFETensor ThisLFETensor; typedef F Field; typedef F field_type; static const DerivativeLayout layout = value; static const unsigned int dimDomain = dimD; static const unsigned int dimRange = dimR; // size needs to be an anonymous enum value for gcc 3.4 compatibility enum { size = ThisLFETensor::size*dimR }; typedef Dune::FieldVector Block; template This &operator=(const FF& f) { for (int r=0; r(f); return *this; } This &operator=(const Dune::FieldVector &t) { tensor_ = t; return *this; } This &operator=(const Block &t) { block() = t; return *this; } This &operator*= ( const field_type &f ) { block() *= f; return *this; } void axpy(const F &a, const This &y) { block().axpy(a,y.block()); } template void assign(const Derivatives &y) { field_cast(y.block(),block()); } template void assign(const Derivatives &y) { for (int rr=0; rr()[0]; } template void assign(const Derivatives &y,unsigned int r) { assign(y.block(),r); } template void assign(unsigned int r,const Derivatives &y) { tensor_[r].assign(y[0]); } template void assign(unsigned int r,const Derivatives &y) { tensor_[r].assign(y[0][0]); } Block &block() { return reinterpret_cast(*this); } const Block &block() const { return reinterpret_cast(*this); } ThisLFETensor &operator[](int r) { return tensor_[r]; } const ThisLFETensor &operator[](int r) const { return tensor_[r]; } template const Dune::FieldVector,dimR> &tensor() const { return tensor_; } Dune::FieldVector,dimR> &tensor() { return tensor_; } template const Dune::FieldVector::size*dimR> &block() const { // use integral_constant here to stay compatible with Int2Type const std::integral_constant a = {}; return reinterpret_cast::size*dimR>&>(tensor(a)); } template Dune::FieldVector::size*dimR> &block() { // use integral_constant here to stay compatible with Int2Type const std::integral_constant a = {}; return reinterpret_cast::size*dimR>&>(tensor(a)); } protected: const Dune::FieldVector,dimR> & tensor(const std::integral_constant &dorderVar) const { return tensor_; } Dune::FieldVector,dimR> & tensor(const std::integral_constant &dorderVar) { return tensor_; } template void assign(const Derivatives &y) { for (int rr=0; rr()[0]; } template void assign(const FieldVector &y,unsigned int r) { tensor_[0] = reinterpret_cast&>(y[r*ThisLFETensor::size]); } template void assign(unsigned int r,const FieldVector &y) { tensor_[r] = y; } Dune::FieldVector tensor_; }; // Implemnetation for derivative based layout template struct Derivatives { typedef Derivatives This; typedef Derivatives ScalarDeriv; typedef F Field; typedef F field_type; static const DerivativeLayout layout = value; static const unsigned int dimDomain = dimD; static const unsigned int dimRange = dimR; // size needs to be an anonymous enum value for gcc 3.4 compatibility enum { size = ScalarDeriv::size*dimR }; typedef Dune::FieldVector Block; template This &operator=(const FF& f) { block() = field_cast(f); return *this; } This &operator=(const Block &t) { block() = t; return *this; } This &operator*= ( const field_type &f ) { block() *= f; return *this; } template void axpy(const FF &a, const This &y) { block().axpy(field_cast(a),y.block()); } // assign with same layout (only different Field) template void assign(const Derivatives &y) { field_cast(y.block(),block()); } // assign with different layout (same dimRange) template void assign(const Derivatives &y) { for (unsigned int rr=0; rr void assign(unsigned int r,const Derivatives &y) { deriv_[r].assign(r,y); } Block &block() { return reinterpret_cast(*this); } const Block &block() const { return reinterpret_cast(*this); } ScalarDeriv &operator[](int r) { return deriv_[r]; } const ScalarDeriv &operator[](int r) const { return deriv_[r]; } protected: Dune::FieldVector deriv_; }; // ****************************************** // AXPY ************************************* // ****************************************** template struct LFETensorAxpy { template static void apply(unsigned int r,const Field &a, const Vec1 &x, Vec2 &y) { y.axpy(a,x); } }; template struct LFETensorAxpy,Vec2,deriv> { typedef Derivatives Vec1; template static void apply(unsigned int r,const Field &a, const Vec1 &x, Vec2 &y) { const FieldVector &xx = x.template block(); for (int i=0; i struct LFETensorAxpy,Vec2,deriv> { typedef Derivatives Vec1; template static void apply(unsigned int r,const Field &a, const Vec1 &x, Vec2 &y) { for (int rr=0; rr, Vec2,deriv>::apply(rr,a,x[rr],y); } }; template struct LFETensorAxpy,Vec2,deriv> { typedef Derivatives Vec1; template static void apply(unsigned int r,const Field &a, const Vec1 &x, Vec2 &y) { LFETensorAxpy, Vec2,deriv>::apply(r,a,x[0],y); } }; template struct LFETensorAxpy,Vec2,deriv> { typedef Derivatives Vec1; template static void apply(unsigned int r,const Field &a, const Vec1 &x, Vec2 &y) { typedef LFETensor LFETensorType; const unsigned int rr = r*LFETensorType::size; const FieldVector &xx = x.template block(); for (int i=0; i::dimension; ++i) y[rr+i] += xx[i]*a; } }; // *********************************************** // Assign **************************************** // *********************************************** template struct DerivativeAssign { static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1,vec2); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.block(),vec2.block()); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { vec2.assign(vec1); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { vec2.assign(vec1); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { vec2.assign(r,vec1); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { vec2.assign(r,vec1); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.block(),vec2.block()); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.block(),vec2.block()); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.block(),vec2.block()); } }; template struct DerivativeAssign, Derivatives > { typedef Derivatives Vec1; typedef Derivatives Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.block(),vec2.block()); } }; template struct DerivativeAssign, F2 > { typedef Derivatives Vec1; typedef F2 Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.block(),vec2); } }; template struct DerivativeAssign,FieldVector > { typedef Derivatives Vec1; typedef FieldVector Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.template block<0>(),vec2); } }; template struct DerivativeAssign,FieldVector > { typedef Derivatives Vec1; typedef FieldVector Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { for (int rr=0; rr()[0].block(),vec2[rr]); } }; template struct DerivativeAssign,FieldVector > { typedef Derivatives Vec1; typedef FieldVector Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.template tensor<0>()[0].block(),vec2[r]); } }; template struct DerivativeAssign,FieldVector > { typedef Derivatives Vec1; typedef FieldVector Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1[0].template tensor<0>()[0].block(),vec2[r]); } }; template struct DerivativeAssign,FieldVector > { typedef Derivatives Vec1; typedef FieldVector Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1.template tensor<0>()[0].block(),vec2); } }; template struct DerivativeAssign,FieldVector > { typedef Derivatives Vec1; typedef FieldVector Vec2; static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) { field_cast(vec1[0].template tensor<0>()[0].block(),vec2); } }; // *********************************************** // IO ******************************************** // *********************************************** template std::ostream &operator<< ( std::ostream &out, const LFETensor< F,dimD,deriv > &tensor ) { return out << tensor.block(); } #if 0 template std::ostream &operator<< ( std::ostream &out, const ScalarDerivatives< F,dimD,deriv > &d ) { out << static_cast &>(d); out << " , " << d.tensor() << std::endl; return out; } template std::ostream &operator<< ( std::ostream &out, const ScalarDerivatives< F,dimD,0 > &d ) { out << d.tensor() << std::endl; return out; } #endif template std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,deriv,derivative > &d ) { out << " ( "; out << d[0]; for (int r=1; r std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,deriv,value > &d ) { out << static_cast &>(d); out << " ( "; out << d[0]; for (int r=1; r std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,0,derivative > &d ) { out << " ( "; out << d[0]; for (int r=1; r std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,0,value > &d ) { out << " ( "; out << d[0]; for (int r=1; r std::ostream &operator<< ( std::ostream &out, const std::vector > &y ) { out << "Number of basis functions: " << y.size() << std::endl; for (unsigned int i=0; i #include #include #include namespace Dune { ////////////////////////////////////////////////////////////////////// // // FiniteElement // //! FiniteElement for lowest order edge elements on simplices /** * Uses the representation * \f[ * \mathbf N^i=(L^{i_0}\nabla L^{i_1}- * L^{i_1}\nabla L^{i_0})\ell^i * \f] * where \f$L^k\f$ is the P1 shape function for vertex \f$k\f$, \f$i_0\f$ * and \f$i_1\f$ are the indices of the vertices of edge \f$i\f$ and * \f$\ell^i\f$ is the length of edge \f$i\f$. * * \ingroup Whitney * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. * \tparam dim Dimension of both domain and range. * * \nosubgrouping */ template class EdgeS0_5FiniteElement { public: /** * \implements FiniteElementInterface::Traits */ struct Traits { typedef EdgeS0_5Basis Basis; typedef EdgeS0_5Interpolation Interpolation; typedef EdgeS0_5Coefficients Coefficients; }; private: typename Traits::Basis basis_; typename Traits::Interpolation interpolation_; static const typename Traits::Coefficients& coefficients_; static const GeometryType gt; public: //! Constructor /** * \copydetails EdgeS0_5Basis::EdgeS0_5Basis(const Geometry& geo, const VertexOrder& vertexOrder) */ template EdgeS0_5FiniteElement(const Geometry& geo, const VertexOrder& vertexOrder) : basis_(geo, vertexOrder), interpolation_(geo, vertexOrder) { } //! return reference to the basis object const typename Traits::Basis& basis() const { return basis_; } //! return reference to the interpolation object const typename Traits::Interpolation& interpolation() const { return interpolation_; } //! return reference to the coefficients object const typename Traits::Coefficients& coefficients() const { return coefficients_; } //! return geometry type of this element const GeometryType& type() const { return gt; } }; template const typename EdgeS0_5FiniteElement::Traits::Coefficients& EdgeS0_5FiniteElement::coefficients_ = typename Traits::Coefficients(); template const GeometryType EdgeS0_5FiniteElement::gt(GeometryType::simplex, Geometry::mydimension); //////////////////////////////////////////////////////////////////////// // // Factory // //! Factory for EdgeS0_5FiniteElement objects /** * Constructs EdgeS0_5FiniteElement objects given a geometry and a vertex * ordering. * * \tparam Geometry Geometry for the local to global transformation. * \tparam RF Field type of the range. * * \implements FiniteElementFactoryInterface */ template struct EdgeS0_5FiniteElementFactory { typedef EdgeS0_5FiniteElement FiniteElement; //! construct the factory /** * \param geometry The geometry object to use for adaption. * \param vertexOrder The global ordering of the vertices within the grid, * used to determine orientation of the edges. This * vertexOrder object must support codim=0. * * \note The returned object stores the reference to the geometry passed * here. Any use of the returned value after this references has * become invalid results in undefined behaviour. The exception is * that the destructor of this class may still be called. The * information contained in the vertexOrder object is extracted and * the object is no longer needed after the contructor returns. No * reference to internal data of the factory is stored. */ template const FiniteElement make(const Geometry& geometry, const VertexOrder& vertexOrder) { return FiniteElement(geometry, vertexOrder); } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_HH dune-localfunctions-2.5.1/dune/localfunctions/whitney/edges0.5/000077500000000000000000000000001313314431100244445ustar00rootroot00000000000000dune-localfunctions-2.5.1/dune/localfunctions/whitney/edges0.5/CMakeLists.txt000066400000000000000000000002321313314431100272010ustar00rootroot00000000000000install(FILES basis.hh coefficients.hh common.hh interpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/whitney/edges0.5) dune-localfunctions-2.5.1/dune/localfunctions/whitney/edges0.5/basis.hh000066400000000000000000000144401313314431100260710ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_BASIS_HH #define DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_BASIS_HH #include #include #include #include #include #include #include namespace Dune { ////////////////////////////////////////////////////////////////////// // // Basis // //! Basis for order 0.5 (lowest order) edge elements on simplices /** * @ingroup BasisImplementation * * \tparam Geometry Type of the local-to-global map. * \tparam RF Type to represent the field in the range. * * \nosubgrouping */ template class EdgeS0_5Basis : private EdgeS0_5Common { public: //! \brief export type traits for function signature struct Traits { typedef typename Geometry::ctype DomainField; static const std::size_t dimDomainLocal = Geometry::mydimension; static const std::size_t dimDomainGlobal = Geometry::coorddimension; typedef FieldVector DomainLocal; typedef FieldVector DomainGlobal; typedef RF RangeField; static const std::size_t dimRange = dimDomainLocal; typedef FieldVector Range; typedef FieldMatrix Jacobian; static const std::size_t diffOrder = 1; }; private: typedef Dune::P1LocalBasis P1LocalBasis; typedef ScalarLocalToGlobalBasisAdaptor P1Basis; static const P1LocalBasis& p1LocalBasis; static const std::size_t dim = Traits::dimDomainLocal; typedef EdgeS0_5Common Base; using Base::refelem; using Base::s; // global values of the Jacobians (gradients) of the p1 basis std::vector p1j; // edge sizes and orientations std::vector edgel; public: //! Construct an EdgeS0_5Basis /** * \param geo Geometry of the element to contruct a local basis * for. * \param vertexOrder Vertex ordering information. Only the vertex order * on the dim=1 sub-entities (edges) is required. */ template EdgeS0_5Basis(const Geometry& geo, const VertexOrder& vertexOrder) : p1j(s, typename P1Basis::Traits::Jacobian(0)), edgel(s) { // use some arbitrary position to evaluate jacobians, they are constant static const typename Traits::DomainLocal xl(0); // precompute Jacobian (gradients) of the p1 element P1Basis(p1LocalBasis, geo).evaluateJacobian(xl, p1j); // calculate edge sizes and orientations for(std::size_t i = 0; i < s; ++i) { edgel[i] = (geo.corner(refelem.subEntity(i,dim-1,0,dim))- geo.corner(refelem.subEntity(i,dim-1,1,dim)) ).two_norm(); const typename VertexOrder::iterator& edgeVertexOrder = vertexOrder.begin(dim-1, i); if(edgeVertexOrder[0] > edgeVertexOrder[1]) edgel[i] *= -1; } } //! number of shape functions std::size_t size () const { return s; } //! Evaluate all shape functions void evaluateFunction(const typename Traits::DomainLocal& xl, std::vector& out) const { out.assign(s, typename Traits::Range(0)); // compute p1 values -- use the local basis directly for that, local and // global values are identical for scalars std::vector p1v; p1LocalBasis.evaluateFunction(xl, p1v); for(std::size_t i = 0; i < s; i++) { const std::size_t i0 = refelem.subEntity(i,dim-1,0,dim); const std::size_t i1 = refelem.subEntity(i,dim-1,1,dim); out[i].axpy( p1v[i0], p1j[i1][0]); out[i].axpy(-p1v[i1], p1j[i0][0]); out[i] *= edgel[i]; } } //! Evaluate all Jacobians void evaluateJacobian(const typename Traits::DomainLocal&, std::vector& out) const { out.resize(s); for(std::size_t i = 0; i < s; i++) { const std::size_t i0 = refelem.subEntity(i,dim-1,0,dim); const std::size_t i1 = refelem.subEntity(i,dim-1,1,dim); for(std::size_t j = 0; j < dim; j++) for(std::size_t k = 0; k < dim; k++) out[i][j][k] = edgel[i] * (p1j[i0][0][k]*p1j[i1][0][j]-p1j[i1][0][k]*p1j[i0][0][j]); } } //! \brief Evaluate partial derivatives of all shape functions void partial (const std::array& order, const typename Traits::DomainLocal& in, // position std::vector& out) const // return value { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); if (totalOrder == 0) { evaluateFunction(in, out); } else if (totalOrder==1) { auto const k = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); for (std::size_t i = 0; i < s; i++) { const std::size_t i0 = refelem.subEntity(i,dim-1,0,dim); const std::size_t i1 = refelem.subEntity(i,dim-1,1,dim); for(std::size_t j = 0; j < dim; j++) out[i][j] = edgel[i] * (p1j[i0][0][k]*p1j[i1][0][j] - p1j[i1][0][k]*p1j[i0][0][j]); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } } //! Polynomial order of the shape functions std::size_t order () const { return 1; } }; template const typename EdgeS0_5Basis::P1LocalBasis& EdgeS0_5Basis::p1LocalBasis = P1LocalBasis(); } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_BASIS_HH dune-localfunctions-2.5.1/dune/localfunctions/whitney/edges0.5/coefficients.hh000066400000000000000000000023471313314431100274340ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_COEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_COEFFICIENTS_HH #include #include #include #include namespace Dune { ////////////////////////////////////////////////////////////////////// // // Coefficients // //! Coefficients for lowest order edge elements on simplices /** * \nosubgrouping * \implements CoefficientsInterface * * \tparam dim Dimension of both domain and range. */ template class EdgeS0_5Coefficients : private EdgeS0_5Common { using EdgeS0_5Common::s; std::vector li; public: //! Standard constructor EdgeS0_5Coefficients() : li(s) { for(std::size_t i = 0; i < s; i++) li[i] = LocalKey(i, dim-1, 0); } //! number of coefficients std::size_t size () const { return s; } //! get i'th index const LocalKey& localKey(std::size_t i) const { return li[i]; } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_COEFFICIENTS_HH dune-localfunctions-2.5.1/dune/localfunctions/whitney/edges0.5/common.hh000066400000000000000000000020601313314431100262530ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_COMMON_HH #define DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_COMMON_HH #include #include namespace Dune { //! Common base class for edge elements template struct EdgeS0_5Common { //! The reference element for this edge element static const ReferenceElement& refelem; //! The number of base functions /** * \note This is not a compile time constant, since the number of edges is * extracted from the reference element. */ static const std::size_t s; }; template const ReferenceElement& EdgeS0_5Common:: refelem(ReferenceElements::simplex()); template const std::size_t EdgeS0_5Common::s(refelem.size(dim-1)); } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_COMMON_HH dune-localfunctions-2.5.1/dune/localfunctions/whitney/edges0.5/interpolation.hh000066400000000000000000000046551313314431100276660ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_INTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_INTERPOLATION_HH #include #include #include namespace Dune { ////////////////////////////////////////////////////////////////////// // // Interpolation // //! Interpolation for lowest order edge elements on simplices /** * \tparam Geometry Type of the local-to-global map. * \tparam RF Type to represent the field in the range. * * \nosubgrouping */ template class EdgeS0_5Interpolation : private EdgeS0_5Common { public: typedef Traits_ Traits; private: static const std::size_t dim = Traits::dimDomainLocal; typedef EdgeS0_5Common Base; using Base::refelem; using Base::s; std::vector edgev; public: //! constructor /** * \param geo Geometry of the element to contruct a local basis * for. * \param vertexOrder Vertex ordering information. Only the vertex order * on the dim=1 sub-entities (edges) is required. */ template EdgeS0_5Interpolation(const Geometry& geo, const VertexOrder& vertexOrder) : edgev(s) { for(std::size_t i = 0; i < s; ++i) { const std::size_t i0 = refelem.subEntity(i,dim-1,0,dim); const std::size_t i1 = refelem.subEntity(i,dim-1,1,dim); edgev[i] = geo.corner(i1); edgev[i] -= geo.corner(i0); edgev[i] /= edgev[i].two_norm(); const typename VertexOrder::iterator& edgeVertexOrder = vertexOrder.begin(dim-1, i); if(edgeVertexOrder[0] > edgeVertexOrder[1]) edgev[i] *= -1; } } //! Interpolation of a function template void interpolate(const F& f, std::vector& out) const { typename Traits::Range y; out.resize(s); for(std::size_t i = 0; i < s; ++i) { f.evaluate(refelem.position(i,dim-1), y); out[i] = y * edgev[i]; } } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_INTERPOLATION_HH