pax_global_header00006660000000000000000000000064141134332720014512gustar00rootroot0000000000000052 comment=f6628171b2773065ab43f97a77f47cd8c4283d8f dune-localfunctions-2.8.0/000077500000000000000000000000001411343327200154755ustar00rootroot00000000000000dune-localfunctions-2.8.0/.gitignore000066400000000000000000000001761411343327200174710ustar00rootroot00000000000000*~ /build*/ # ignore files generated during python setup.py sdist MANIFEST _skbuild/ dist # ignore macOS filesystem .DS_Store dune-localfunctions-2.8.0/.gitlab-ci.yml000066400000000000000000000034211411343327200201310ustar00rootroot00000000000000--- include: - project: 'core/ci-config' ref: master file: 'config/common/master.yml' - project: 'core/ci-config' ref: master file: 'jobs/common/master.yml' before_script: - . /duneci/bin/duneci-init-job - 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-11-gcc-9-17-python: image: registry.dune-project.org/docker/ci/debian:11 script: duneci-standard-test variables: DUNECI_TOOLCHAIN: gcc-9-17 # so we need some variables to build the dune-py module during execution of the first python test: # we need to find the dune mdoule DUNE_CONTROL_PATH: /duneci/modules:$CI_PROJECT_DIR # the position for the dune-py module DUNE_PY_DIR: /duneci/modules/dune-py # during dune-py build this variable is used - do know a way to access # the CMAKE_FLAGS used to build the modules... DUNE_CMAKE_FLAGS: "-DCMAKE_CXX_COMPILER=g++-9 -DCMAKE_C_COMPILER=gcc-9 -DCMAKE_CXX_FLAGS='-std=c++17 -O2 -g -Wall -fdiagnostics-color=always' -DDUNE_ENABLE_PYTHONBINDINGS=ON -DDUNE_MAX_TEST_CORES=4 -DBUILD_SHARED_LIBS=TRUE -DDUNE_PYTHON_INSTALL_LOCATION=none -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_DISABLE_FIND_PACKAGE_LATEX=TRUE -DCMAKE_DISABLE_FIND_PACKAGE_Alberta=TRUE -DCMAKE_DISABLE_FIND_PACKAGE_Vc=TRUE -DCMAKE_DISABLE_DOCUMENTATION=TRUE" # cmake flags we use for all dune moudle - important is that build shared libs is set (need some better way of doing this) DUNECI_CMAKE_FLAGS: $DUNE_CMAKE_FLAGS # finally set the python path to all modules PYTHONPATH: /duneci/modules/dune-common/build-cmake/python:/duneci/modules/dune-geometry/build-cmake/python:$CI_PROJECT_DIR/build-cmake/python tags: [duneci] dune-localfunctions-2.8.0/CHANGELOG.md000066400000000000000000000127271411343327200173170ustar00rootroot00000000000000# Release 2.8 * Passing functions that support `f.evaluate(x,y)` to `interpolate()` is deprecated. Instead the functions should now provide `operator()`. Passing functions providing the old interface is still supported in 2.8. * `LocalFiniteElementFunctionBase` is deprecated. You can rely on duck-typing when passing functions with the new interface. * The virtual interface for interpolating functions in `LocalFiniteElementVirtualInterface` now uses `std::function` instead of the deprecated `VirtualFunction` for the passed function. * The virtual interface wrapper `LocalFiniteElementVirtualImp` now requires that the wrapped `LocalFiniteElement` implementation supports the new `operator()` based interpolation interface. * Add an implementation of the Nédélec element of the first kind, as introduced in "Nédélec, Mixed finite elements in R^3, 1980, DOI: http://dx.doi.org/10.1007/BF01396415". Only the first-order case for triangles, tetrahedra, squares and cubes is implemented. * Fix a bug in a shape function of the second-order Lagrange element on the three-dimensional pyramid. * Add an implementation of the Raviart-Thomas element for tetrehedra with order 0. * Remove deprecated `GenericLocalFiniteElement::topologyId()`, use `type().id()` instead. * Imported the Python bindings from the 2.7 branch of dune-python. * Replaced the combination of function arguments `topologyId` and `dim` with a single `GeometryType` argument. Tagged the old versions of: `numLagrangePoints`, `equidistantLagrangePoints`, `RTL2InterpolationBuilder::topologyId()`, `VirtualMonomialBasis(topologyId)`, `VirtualMonomialBasis::topologyId()` as deprecated. * Add a construction algorithm for high order Nédélec elements on triangles and tetrahedra. # Release 2.7 * The header `lagrange.hh` now includes all headers of all Lagrange implementations, not just the ones with run-time order. * Introduce a run-time polymorphic container `LocalFiniteElementVariant`. Much like `std::variant`, it implements a type-safe union of different `LocalFiniteElement` implementations. Elements of type `LocalFiniteElementVariant` can hold one object from a list of types given as template parameters. These types must be implementations of the `LocalFiniteElement` interface, and the container will in turn implement this interface. Such a `variant`-based polymorphism is not as flexible as full type erasure, but it is much easier to implement. What is more, it is believed that in many situations the restriction to a fixed set of implementation types is not a problem. * Add support for `operator()` syntax to `interpolate()`. All `interpolate()` implementations now support functions `f` that either support `f.evaluate(x,y)` or `y = f(x)`. * Add an implementation of the Crouzeix-Raviart element. * Add an implementation of the Brezzi-Douglas-Fortin-Marini element. The coefficients and interpolation are implemented for arbitrary dimension (>1) and order (>0). The actual basis is only implemented for dim=2 and order=1,2,3. See core/dune-localfunctions!105 and core/dune-localfunctions!145 * Introduce a convenience header `hierarchical.hh` that includes all hierarchical FE implementations. * Introduce a new class `LagrangeSimplexLocalFiniteElement`, which implements Lagrange finite elements on simplices with compile-time dimension and order. It currently does not cover more general dimension/order situations than what is already available in dune-localfunctions, but it gathers the plethora of different Pk3DNodal, PkNodal, P1Nodal, etc implementations under one single name. * Introduce new class `BrezziDouglasMariniSimplexLocalFiniteElement` (and the same for cubes) that subsumes all currently existing simplex BDM element implementations under a single name. Domain dimension and polynomial order are template parameters now. * Introduce a convenience header `dune/localfunctions/brezzidouglasmarini.hh` that includes all BDM implementations. # Release 2.6 * The `diffOrder` value has disappeared from the `LocalBasisTraits` class. This value encoded the highest partial derivative order implemented by a local basis. Encoding this value as a compile-time parameter led to various problems related to the dynamic interface, mainly because it became part of the type of the local finite element. At the same time, it was suspected that very few people ever actually used the parameter. More practically, two things have disappeared: the `diffOrder` member of the `LocalBasisTraits` class, and the 8th template parameter `dorder` of that class. There is no replacement, and if you have used `diffOrder` then you currently have to find a way to live without it. As mentioned we believe that this concerns only a very small number of people. If you do use `diffOrder` and you absolutely need it or something similar, then we'd like to hear from you. One of the reasons why there is no replacement is that we couldn't really think of a good use case to begin with. * The `QkLocalFiniteElement` class implements second partial derivatives of shape functions now. * The `clone()` method was removed from the raw (non-virtual) `LocalFiniteElement` implementations. If you want to copy a `LocalFiniteElement` in a portable way which works for raw implementations as well as for the virtual interface class, you have to replace `lfe.clone()` by `Dune::LocalFiniteElementCloneFactory::clone(lfe)`. dune-localfunctions-2.8.0/CMakeLists.txt000066400000000000000000000015261411343327200202410ustar00rootroot00000000000000# set up project project("dune-localfunctions" C CXX) # general stuff cmake_minimum_required(VERSION 3.13) # 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) if( DUNE_ENABLE_PYTHONBINDINGS ) add_subdirectory(python) dune_python_install_package(PATH python) endif() finalize_dune_project(GENERATE_CONFIG_H_CMAKE) dune-localfunctions-2.8.0/COPYING000077700000000000000000000000001411343327200201272LICENSE.mdustar00rootroot00000000000000dune-localfunctions-2.8.0/INSTALL000066400000000000000000000046621411343327200165360ustar00rootroot00000000000000Installation 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.8.0/LICENSE.md000066400000000000000000000474461411343327200171200ustar00rootroot00000000000000Copyright holders: 2015--2016 Marco Agnese 2008--2010 Peter Bastian 2015 Timo Betcke 2009--2014 Markus Blatt 2016 Lukas Böger 2014 Andreas Buhr 2014--2017 Ansgar Burchardt 2009--2021 Andreas Dedner 2020 Nils-Arne Dreier 2010 Martin Drohmann 2008--2020 Christian Engwer 2008--2020 Jorrit Fahlke 2011--2013 Bernd Flemisch 2015 Elisa Friebel 2012 Christoph Gersbacher 2019 Janick Gerstenberger 2009--2021 Carsten Gräser 2015--2018 Felix Gruber 2011--2021 Christoph Grüninger 2020 René Heß 2017 Patrick Jaap 2013 Guillaume Jouvet 2015--2020 Dominic Kempf 2015 Angela Klewinghaus 2020 Robert Klöfkorn 2014 Arne Morten Kvarving 2015 Jizhou Li 2013--2017 Tobias Malkmus 2009 Sven Marnach 2013--2018 Steffen Müthing 2020 Lisa Julia Nebel 2012 Rebecca Neumann 2008--2018 Martin Nolte 2011--2016 Elias Pipping 2016--2021 Simon Praetorius 2012--2013 Human Rezaijafari 2011--2012 Uli Sack 2008--2021 Oliver Sander 2020--2021 Henrik Stolzmann 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.8.0/README.md000066400000000000000000000017001411343327200167520ustar00rootroot00000000000000DUNE-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.8.0/config.h.cmake000066400000000000000000000026051411343327200201750ustar00rootroot00000000000000/* 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.8.0/doc/000077500000000000000000000000001411343327200162425ustar00rootroot00000000000000dune-localfunctions-2.8.0/doc/CMakeLists.txt000066400000000000000000000002301411343327200207750ustar00rootroot00000000000000add_subdirectory(doxygen) dune_add_latex_document( SOURCE dune-localfunctions-manual.tex FATHER_TARGET doc INSTALL ${CMAKE_INSTALL_DOCDIR}/comm) dune-localfunctions-2.8.0/doc/doxygen/000077500000000000000000000000001411343327200177175ustar00rootroot00000000000000dune-localfunctions-2.8.0/doc/doxygen/CMakeLists.txt000066400000000000000000000001121411343327200224510ustar00rootroot00000000000000# shortcut for creating the Doxyfile.in and Doxyfile add_doxygen_target() dune-localfunctions-2.8.0/doc/doxygen/Doxylocal000066400000000000000000000002661411343327200216040ustar00rootroot00000000000000# Where to search and which files to use INPUT += @srcdir@/mainpage.txt \ @srcdir@/modules.txt \ @top_srcdir@/dune/ dune-localfunctions-2.8.0/doc/doxygen/mainpage.txt000066400000000000000000000006461411343327200222470ustar00rootroot00000000000000/** \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.8.0/doc/doxygen/modules.txt000066400000000000000000000016151411343327200221330ustar00rootroot00000000000000/** * \defgroup LocalFunctions LocalFunctions */ /** * \defgroup BrezziDouglasFortinMarini Brezzi-Douglas-Fortin-Marini elements * \ingroup 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.8.0/doc/dune-localfunctions-manual.tex000066400000000000000000001632241411343327200242230ustar00rootroot00000000000000\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 always 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 Raviart-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. % bibtex bibliography %\bibliographystyle{plain} %\bibliography{istl.bib} \end{document} dune-localfunctions-2.8.0/dune-localfunctions.pc.in000066400000000000000000000004171411343327200224040ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ CXX=@CXX@ CC=@CC@ DEPENDENCIES=@REQUIRES@ Name: @PACKAGE_NAME@ Version: @VERSION@ Description: @DESCRIPTION@ URL: @URL@ Requires: ${DEPENDENCIES} Libs: -L${libdir} Cflags: -I${includedir} dune-localfunctions-2.8.0/dune.module000066400000000000000000000005541411343327200176430ustar00rootroot00000000000000Module: dune-localfunctions Version: 2.8.0 Author: The Dune Core developers Maintainer: dune-devel@lists.dune-project.org Description: Provides interface and implementation for shape functions defined on the DUNE reference elements URL: https://gitlab.dune-project.org/core/dune-localfunctions Python-Requires: Depends: dune-geometry (>= 2.8) Whitespace-Hook: Yes dune-localfunctions-2.8.0/dune/000077500000000000000000000000001411343327200164305ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/CMakeLists.txt000066400000000000000000000001501411343327200211640ustar00rootroot00000000000000add_subdirectory(localfunctions) if( DUNE_ENABLE_PYTHONBINDINGS ) add_subdirectory("python") endif() dune-localfunctions-2.8.0/dune/localfunctions/000077500000000000000000000000001411343327200214535ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/CMakeLists.txt000066400000000000000000000020731411343327200242150ustar00rootroot00000000000000add_subdirectory(brezzidouglasfortinmarini) add_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(nedelec) add_subdirectory(orthonormal) add_subdirectory(rannacherturek) add_subdirectory(raviartthomas) add_subdirectory(refined) add_subdirectory(test) add_subdirectory(utility) add_subdirectory(whitney) install(FILES brezzidouglasmarini.hh crouzeixraviart.hh dualmortarbasis.hh hierarchical.hh lagrange.hh mimetic.hh monomial.hh nedelec.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.8.0/dune/localfunctions/brezzidouglasfortinmarini/000077500000000000000000000000001411343327200267615ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasfortinmarini/CMakeLists.txt000066400000000000000000000002451411343327200315220ustar00rootroot00000000000000set(HEADERS bdfmcube.hh ) add_subdirectory(cube) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasfortinmarini) dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasfortinmarini/bdfmcube.hh000066400000000000000000000055511411343327200310570ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_BDFMCUBE_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_BDFMCUBE_HH #include #include #include #include #include namespace Dune { /** * \brief Brezzi-Douglas-Fortin-Marini finite elements for cubes * * Brezzi-Douglas-Fortin-Marini (BDFM) finite elements are reduced * Brezzi-Douglas-Marini (BDM) finite elements, where the order of * the normal traces is lowered by one. * * On a quadrilateral K the BDFM element is given by * * \f$BDFM_k = (P_k(K)\setminus\{y^k\})\times(P_k(K)\setminus\{x^k\})\quad(k\geq1)\f$ * * The BDFM1 element is identical to the RT0 element. * * For further reading see * Brezzi, Fortin "Mixed and Hybrid Finite Element Methods" (1991), Chapter III Section 3 * * \ingroup BrezziDouglasFortinMarini * * \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. * \tparam order order of the element, must be >= 1. */ template class BDFMCubeLocalFiniteElement { using LocalBasis = BDFMCubeLocalBasis; using LocalCoefficients = BDFMCubeLocalCoefficients; using LocalInterpolation = BDFMCubeLocalInterpolation; public: using Traits = LocalFiniteElementTraits; //! \brief Standard constructor BDFMCubeLocalFiniteElement () {} /** * \brief Make set number s, where 0 <= s < 2^(2*dim) * * \param s Edge orientation indicator */ BDFMCubeLocalFiniteElement (std::bitset<2*dim> s) : basis( s ), interpolation( s ) {} auto localBasis () const -> const LocalBasis& { return basis; } auto localCoefficients () const -> const LocalCoefficients& { return coefficients; } auto localInterpolation () const -> const LocalInterpolation& { return interpolation; } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return basis.size(); } static constexpr auto type () -> GeometryType { return GeometryTypes::cube(dim); } private: LocalBasis basis; LocalCoefficients coefficients; LocalInterpolation interpolation; }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_BDFMCUBE_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasfortinmarini/cube/000077500000000000000000000000001411343327200276775ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasfortinmarini/cube/CMakeLists.txt000066400000000000000000000003031411343327200324330ustar00rootroot00000000000000set(HEADERS localbasis.hh localcoefficients.hh localinterpolation.hh ) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasfortinmarini/cube) dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasfortinmarini/cube/localbasis.hh000066400000000000000000000264051411343327200323430ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALBASIS_HH #include #include #include #include #include #include #include #include #include #include #include namespace Dune { /** * \ingroup LocalBasisImplementation * \brief Brezzi-Douglas-Fortin-Marini shape functions on a 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 reference element, must be >= 2. * \tparam order order of the element, must be >= 1. * * \nosubgroup */ template class BDFMCubeLocalBasis { static_assert( AlwaysFalse::value, "`BDFMCubeLocalBasis` not implemented for chosen `dim` and `order`." ); }; #ifndef DOXYGEN template class BDFMCubeLocalBasis { static_assert( AlwaysFalse::value, "`BDFMCubeLocalBasis` not defined for order 0." ); }; #endif // #ifndef DOXYGEN /** * \brief First order Brezzi-Douglas-Fortin-Marini shape functions on the refrence quadrialteral. * * \nosubgrouping */ template class BDFMCubeLocalBasis { using DomainType = FieldVector; using RangeType = FieldVector; using JacobianType = FieldMatrix; public: using Traits = LocalBasisTraits; //! \brief Standard constructor BDFMCubeLocalBasis () { std::fill(s_.begin(), s_.end(), 1); } /** * \brief Make set number s, where 0<= s < 16 * * \param s Edge orientation indicator */ BDFMCubeLocalBasis (std::bitset<4> s) { for (auto i : range(4)) s_[i] = s[i] ? -1 : 1; } //! \brief number of shape functions unsigned int size () const { return 4; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const DomainType& in, std::vector& out) const { out.resize(4); out[0] = {s_[0]*(in[0]-1), 0 }; out[1] = {s_[1]*(in[0]) , 0 }; out[2] = {0, s_[2]*(in[1]-1)}; out[3] = {0, s_[3]*(in[1]) }; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const DomainType& in, std::vector& out) const { out.resize(4); out[0] = {{s_[0], 0}, {0, 0}}; out[1] = {{s_[1], 0}, {0, 0}}; out[2] = {{0, 0}, {0, s_[2]}}; out[3] = {{0, 0}, {0, s_[3]}}; } /** * \brief Evaluate all partial derivatives of all shape functions * * \param order order the partial derivative * \param in Position * \param out return value */ void partial (const std::array& order, const DomainType& in, std::vector& out) const { if (std::accumulate(order.begin(), order.end(), 0) == 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 s_; }; /** * \brief Second order Brezzi-Douglas-Fortin-Marini shape functions on the refrence quadrialteral. * * \nosubgrouping */ template class BDFMCubeLocalBasis { using DomainType = FieldVector; using RangeType = FieldVector; using JacobianType = FieldMatrix; public: using Traits = LocalBasisTraits; //! \brief Standard constructor BDFMCubeLocalBasis () { std::fill(s_.begin(), s_.end(), 1); } /** * \brief Make set number s, where 0<= s < 16 * * \param s Edge orientation indicator */ BDFMCubeLocalBasis (std::bitset<4> s) { for (auto i : range(4)) s_[i] = s[i] ? -1 : 1; } //! \brief number of shape functions unsigned int size () const { return 10; } /** * \brief Evaluate all shape functions * * \param in Position * \param out return value */ inline void evaluateFunction (const DomainType& in, std::vector& out) const { out.resize(10); const auto& x = in[0]; const auto& y = in[1]; auto pre = 1-x; out[0] = {pre*s_[0]*(3*x-1), 0}; out[1] = { pre*3*(2*y-1), 0}; pre = x; out[2] = {pre*s_[1]*(3*x-2), 0}; out[3] = {pre* 3*(2*y-1), 0}; pre = 1-y; out[4] = {0, pre*s_[2]*(3*y-1)}; out[5] = {0, pre*3*(2*x-1)}; pre = y; out[6] = {0, pre*s_[3]*(3*y-2)}; out[7] = {0, pre*3*(2*x-1)}; out[8] = {6*x*(1-x), 0}; out[9] = {0, 6*y*(1-y)}; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const DomainType& in, std::vector& out) const { out.resize(10); const auto& x = in[0]; const auto& y = in[1]; out[0] = {{s_[0]*(4-6*x), 0}, {0, 0}}; out[1] = {{3-6*y, 6-6*x}, {0, 0}}; out[2] = {{s_[1]*(6*x-2), 0}, {0, 0}}; out[3] = {{6*y-3, 6*x}, {0, 0}}; out[4] = {{0, 0}, {0, s_[2]*(4-6*y)}}; out[5] = {{0, 0}, {6-6*y, 3-6*x}}; out[6] = {{0, 0}, {0, s_[3]*(6*y-2)}}; out[7] = {{0, 0}, {6*y, 6*x-3}}; out[8] = {{6-12*x, 0}, {0, 0}}; out[9] = {{0, 0}, {0, 6-12*y}}; } /** * \brief Evaluate all partial derivatives of all shape functions * * \param order order the partial derivative * \param in Position * \param out return value */ void partial (const std::array& order, const DomainType& in, std::vector& out) const { if (std::accumulate(order.begin(), order.end(), 0) == 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 2; } private: std::array s_; }; /** * \brief Third order Brezzi-Douglas-Fortin-Marini shape functions on the refrence quadrialteral. * * \nosubgrouping */ template class BDFMCubeLocalBasis { using DomainType = FieldVector; using RangeType = FieldVector; using JacobianType = FieldMatrix; public: using Traits = LocalBasisTraits; //! \brief Standard constructor BDFMCubeLocalBasis () { std::fill(s_.begin(), s_.end(), 1); } /** * \brief Make set number s, where 0<= s < 16 * * \param s Edge orientation indicator */ BDFMCubeLocalBasis (std::bitset<4> s) { for (auto i : range(4)) s_[i] = s[i] ? -1 : 1; } //! \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 DomainType& in, std::vector& out) const { out.resize(18); const auto& x = in[0]; const auto& y = in[1]; auto pre = 1-x; out[0] = {pre*s_[0]*-1*(10*x*x-8*x+1), 0}; out[1] = {pre* 3*(1-3*x)*(2*y-1), 0}; out[2] = {pre* s_[0]*-5*(6*y*y-6*y+1), 0}; pre = x; out[3] = {pre*s_[1]*(10*x*x-12*x+3), 0}; out[4] = {pre* 3*(3*x-2)*(2*y-1), 0}; out[5] = {pre*s_[1]*5*(6*y*y-6*y+1), 0}; pre = 1-y; out[6] = {0, pre*s_[2]*-1*(10*y*y-8*y+1)}; out[7] = {0, pre* 3*(1-3*y)*(2*x-1)}; out[8] = {0, pre*s_[2]*-5*( 6*x*x-6*x+1)}; pre = y; out[9] = {0, pre*s_[3]*(10*y*y-12*y+3)}; out[10] = {0, pre* 3*(3*y-2)*(2*x-1)}; out[11] = {0, pre*s_[3]*5*(6*x*x-6*x+1)}; pre = x*(1-x); out[12] = {pre* 6 , 0}; out[14] = {pre*30*(2*x-1), 0}; out[16] = {pre*18*(2*y-1), 0}; pre = y*(1-y); out[13] = {0, pre* 6 }; out[15] = {0, pre*18*(2*x-1)}; out[17] = {0, pre*30*(2*y-1)}; } /** * \brief Evaluate Jacobian of all shape functions * * \param in Position * \param out return value */ inline void evaluateJacobian (const DomainType& in, std::vector& out) const { out.resize(18); const auto& x = in[0]; const auto& y = in[1]; out[0] = {{s_[0]*(30*x*x-36*x+9), 0}, {0, 0}}; out[1] = {{ 6*(6*x*y-3*x-4*y+2), 6*(3*x*x-4*x+1)}, {0, 0}}; out[2] = {{s_[0]*5*(6*y*y-6*y+1), s_[0]*30*(x-1)*(2*y-1)}, {0, 0}}; out[3] = {{ s_[1]*30*x*x-24*x+3, 0}, {0, 0}}; out[4] = {{ 6*(3*x-1)*(2*y-1), 6*x*(3*x-2)}, {0, 0}}; out[5] = {{s_[1]*5*(6*y*y-6*y+1), s_[1]*30*x*(2*y-1)}, {0, 0}}; out[6] = {{0, 0}, { 0, s_[2]*(30*y*y-36*y+9)}}; out[7] = {{0, 0}, { 6*(3*y*y-4*y+1), 6*(6*y*x-3*y-4*x+2)}}; out[8] = {{0, 0}, {s_[2]*30*(y-1)*(2*x-1), s_[2]*5*(6*x*x-6*x+1)}}; out[9] = {{0, 0}, { 0, s_[3]*30*y*y-24*y+3}}; out[10] = {{0, 0}, { 6*y*(3*y-2), 6*(3*y-1)*(2*x-1)}}; out[11] = {{0, 0}, {s_[3]*30*y*(2*x-1), s_[3]*5*(6*x*x-6*x+1)}}; out[12] = {{ -6*(2*x-1), 0}, {0, 0}}; out[14] = {{ -30*(6*x*x-6*x+1), 0}, {0, 0}}; out[16] = {{-18*(2*x-1)*(2*y-1), 36*x*(1-x)}, {0, 0}}; out[13] = {{0, 0}, { 0, -6*(2*y-1)}}; out[15] = {{0, 0}, {36*y*(1-y), -18*(2*y-1)*(2*x-1)}}; out[17] = {{0, 0}, { 0, -30*(6*y*y-6*y+1)}}; } /** * \brief Evaluate all partial derivatives of all shape functions * * \param order order the partial derivative * \param in Position * \param out return value */ void partial (const std::array& order, const DomainType& in, std::vector& out) const { if (std::accumulate(order.begin(), order.end(), 0) == 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: std::array s_; }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALBASIS_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasfortinmarini/cube/localcoefficients.hh000066400000000000000000000054141411343327200337000ustar00rootroot00000000000000#ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALCOEFFICIENTS_HH #include #include #include #include #include #include namespace Dune { /** * \ingroup LocalLayoutImplementation * * \brief Layout map for Brezzi-Douglas-Fortin-Marini elements on cubes. * * \tparam D Type of represent the field in the domain. * \tparam R Type of represent the field in the domain. * \tparam dim dimension of the reference element, must be >= 2. * \tparam order order of the element, must be >= 1. * * \nosubgrouping * \implements Dune::LocalCoefficientsVirtualImp */ template class BDFMCubeLocalCoefficients { static constexpr unsigned int interiorDofs = dim*binomial(dim+order-2, order-2); static constexpr unsigned int faceDofs = binomial(dim+order-2, order-1); static constexpr std::size_t numFaces = 2*dim; static constexpr std::size_t numDofs = numFaces*faceDofs + interiorDofs; public: //! \brief Standard constructor BDFMCubeLocalCoefficients () : li(numDofs) { for (auto j : range(numFaces)) for (auto i : range(faceDofs)) li[j*faceDofs + i] = LocalKey(j, 1, i); for (auto i : range(interiorDofs)) li[numFaces*faceDofs + i] = LocalKey(0, 0, i); } //! \brief number of coefficients std::size_t size () const { return numDofs; } //! \brief geth i'th index auto localKey (std::size_t i) const -> const LocalKey& { return li[i]; } private: std::vector li; }; template constexpr unsigned int BDFMCubeLocalCoefficients::interiorDofs; template constexpr unsigned int BDFMCubeLocalCoefficients::faceDofs; template constexpr std::size_t BDFMCubeLocalCoefficients::numFaces; // template // constexpr std::size_t BDFMCubeLocalCoefficients::numDofs; #ifndef DOXYGEN template class BDFMCubeLocalCoefficients { static_assert( AlwaysFalse::value, "`BDFMCubeLocalCoefficients` not defined for order 0." ); }; #endif // #ifndef DOXYGEN } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALCOEFFICIENTS_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasfortinmarini/cube/localinterpolation.hh000066400000000000000000000174751411343327200341400ustar00rootroot00000000000000#ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALINTERPOLATION_HH #include #include #include #include #include #include #include #include #include #include #include namespace Dune { /** * \ingroup LocalInterpolationImplementation * \brief Interpolation for Brezzi-Douglas-Fortin-Marini shape functions on cubes. * * \tparam D Type of represent the field in the domain. * \tparam R Type of represent the field in the domain. * \tparam dim dimension of the reference element, must be >= 2. * \tparam order order of the element, must be >= 1. * * \nosubgrouping */ template class BDFMCubeLocalInterpolation { using DomainType = FieldVector; using FaceDomainType = FieldVector; using RangeType = FieldVector; using DomainFieldType = D; using RangeFieldType = R; static constexpr std::size_t numFaces = 2*dim; static constexpr unsigned int interiorDofs = dim*binomial(dim+order-2, order-2); static constexpr unsigned int faceDofs = binomial(dim+order-2, order-1); /** * \brief compute the i'th shifted Legendre function on [0,1] * * \param i index of function to compute * \param x Position */ inline static auto legendre( unsigned int i, const DomainFieldType& x ) -> RangeFieldType { switch( i ) { case 0: return 1; case 1: return 2*x-1; case 2: return 6*x*x-6*x+1; case 3: return 20*x*x*x-30*x*x+12*x-1; default: return ((2*i-1)*(2*x-1)*legendre(x,i-1) - (i-1)*legendre(x,i-2)) / i; } } /** * \brief calculate the i`th multi index in graded lexigraphic order * * \tparam d number of components of the multi index * \tparam kMax maximum absolute value to consider. (default is `unlimited`) * * \param i index * */ template::max()> constexpr inline static auto unrank (std::size_t i) -> std::array { assert( i < binomial(d+kMax, kMax)); std::array mi{}; if (i == 0) return mi; std::size_t k = 0, b = 1; for(;k <= kMax && b <= i; ++k, b = binomial(d+k-1, k)) i -= b; std::size_t p = 0; for(; p < d && i > 0; ++p) { std::size_t m = 0, c = 1; for(; m <= k && c <= i; ++m, c = binomial(d-p+m-2, m)) i -= c; mi[p] = k-m; k = m; } mi[p] = k; return mi; } /** * \brief embed the a local position on a face into the reference element * * \param face index of the face * \param x local position */ inline static auto embed (unsigned int face, const FaceDomainType& x ) -> DomainType { DomainType y; std::size_t j = 0; for (auto i : range(dim)) if (i == face/2) y[i] = face%2; else y[i] = x[j++]; return y; } public: //! \brief Standard constructor BDFMCubeLocalInterpolation () { std::fill(sign_.begin(), sign_.end(), 1.0); } /** * \brief Make set number s, where 0 <= s < 2^(2*dim) * * \param s Edge orientation indicator */ BDFMCubeLocalInterpolation (std::bitset s) { for (auto i : range(numFaces)) { sign_[i] = s[i] ? -1 : 1; normal_[i][i/2] = i%2 ? 1 : -1; } } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient vector type * * \param ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, C& out) const { out.resize(numFaces*faceDofs + interiorDofs); std::fill(out.begin(),out.end(), 0.0); auto&& f = Impl::makeFunctionWithCallOperator(ff); for(auto i : range(numFaces)) trace(i, f, out); interior(f, out); } /** * \brief Interpolate a given function with shape functions on a face of the reference element * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient vector type * * \param face index of the face on which to interpolate * \param f function which should be interpolated * \param out return value, vector of coefficients * */ template void trace (unsigned int face, const F& f, C& out) const { assert(out.size() >= numFaces*faceDofs + interiorDofs); assert(face < numFaces); const auto o = face*faceDofs; const auto& n = normal_[face]; const auto& s = sign_[face]; const auto& c = n[face/2]; const auto& rule = QuadratureRules::rule(GeometryTypes::cube(dim-1), order+(order-1)+5); for (const auto& qp : rule) { const auto& x = qp.position(); auto y = f(embed(face, x)); for (auto i : range(faceDofs)) { auto mi = unrank(i); RangeFieldType phi = 1.; for (auto j : range(dim-1)) phi *= legendre(mi[j], x[j]); out[o+i] += (y*n) * phi * qp.weight() * (i%2 ? c : s); } } } /** * \brief Interpolate a given function with shape functions in the interior of the reference element * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient vector type * * \param ff function which should be interpolated * \param out return value, vector of coefficients */ template void interior (const F& f, C& out) const { assert(out.size() >= numFaces*faceDofs + interiorDofs); const auto o = numFaces*faceDofs; const auto& rule = QuadratureRules::rule(GeometryTypes::cube(dim), order+std::max((int)order-2,(int)0)+5); for(const auto& qp : rule) { const auto& x = qp.position(); auto y = f(x); for (auto i : range(interiorDofs/dim)) { auto mi = unrank(i); RangeFieldType phi = 1.; for (auto j : range(dim)) phi *= legendre(mi[j], x[j]); for (auto j : range(dim)) out[o+dim*i+j] += y[j]* phi * qp.weight(); } } } private: std::array sign_; std::array normal_; }; template constexpr std::size_t BDFMCubeLocalInterpolation::numFaces; template constexpr unsigned int BDFMCubeLocalInterpolation::interiorDofs; template constexpr unsigned int BDFMCubeLocalInterpolation::faceDofs; #ifndef DOXYGEN template class BDFMCubeLocalInterpolation { static_assert(AlwaysFalse::value, "`BDFMCubeLocalCoefficients` not defined for order 0."); }; #endif //#ifndef DOXYGEN } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASFORTINMARINI_CUBE_LOCALINTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini.hh000066400000000000000000000007241411343327200260630ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_HH // BDM implementations with compile-time order #include #include #endif // #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/000077500000000000000000000000001411343327200255375ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/CMakeLists.txt000066400000000000000000000010541411343327200302770ustar00rootroot00000000000000add_subdirectory(brezzidouglasmarini1cube2d) add_subdirectory(brezzidouglasmarini1cube3d) add_subdirectory(brezzidouglasmarini2cube2d) add_subdirectory(brezzidouglasmarini1simplex2d) add_subdirectory(brezzidouglasmarini2simplex2d) install(FILES brezzidouglasmarinicube.hh brezzidouglasmarinisimplex.hh brezzidouglasmarini1cube2d.hh brezzidouglasmarini1cube3d.hh brezzidouglasmarini2cube2d.hh brezzidouglasmarini1simplex2d.hh brezzidouglasmarini2simplex2d.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini) dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d.hh000066400000000000000000000042741411343327200333210ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ BDM1Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::quadrilateral; } private: BDM1Cube2DLocalBasis basis; BDM1Cube2DLocalCoefficients coefficients; BDM1Cube2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_QUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d/000077500000000000000000000000001411343327200327715ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004111411343327200354460ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2dinstall(FILES brezzidouglasmarini1cube2dlocalbasis.hh brezzidouglasmarini1cube2dlocalcoefficients.hh brezzidouglasmarini1cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d) brezzidouglasmarini1cube2dlocalbasis.hh000066400000000000000000000133311411343327200425230ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000022141411343327200440610ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000070761411343327200443220ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(8); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const QuadratureRule& rule = QuadratureRules::rule(GeometryTypes::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; auto y = f(localPos); 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; y = f(localPos); 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; y = f(localPos); 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; y = f(localPos); 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.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d.hh000066400000000000000000000043061411343327200333160ustar00rootroot00000000000000// -*- 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() {} /** * \brief Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ BDM1Cube3DLocalFiniteElement(int s) : basis(s) , interpolation(s) {} 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(); } static constexpr GeometryType type() { return GeometryTypes::hexahedron; } private: BDM1Cube3DLocalBasis basis; BDM1Cube3DLocalCoefficients coefficients; BDM1Cube3DLocalInterpolation > interpolation; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_QUBE3D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d/000077500000000000000000000000001411343327200327725ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004111411343327200354470ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3dinstall(FILES brezzidouglasmarini1cube3dlocalbasis.hh brezzidouglasmarini1cube3dlocalcoefficients.hh brezzidouglasmarini1cube3dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d) brezzidouglasmarini1cube3dlocalbasis.hh000066400000000000000000000265071411343327200425360ustar00rootroot00000000000000dune-localfunctions-2.8.0/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; out[0][2] = 0; out[1][0] = sign_[1] * in[0]; out[1][1] = 0; out[1][2] = 0; out[2][0] = 0; out[2][1] = sign_[2] * (in[1] - 1.0); out[2][2] = 0; out[3][0] = 0; out[3][1] = sign_[3] * in[1]; out[3][2] = 0; out[4][0] = 0; out[4][1] = 0; out[4][2] = sign_[4] * (in[2] - 1.0); out[5][0] = 0; out[5][1] = 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; 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; 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; 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; out[10][0] = -3.0 * in[0] * in[0] + 3 * in[0]; out[10][1] = 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; 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; 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; out[13][2] = -3.0 * in[2] * in[2] + 3 * in[2]; out[14][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; 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; 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; 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] = { sign_[0], 0, 0}; out[0][1] = { 0, 0, 0}; out[0][2] = { 0, 0, 0}; out[1][0] = { sign_[1], 0, 0}; out[1][1] = { 0, 0, 0}; out[1][2] = { 0, 0, 0}; out[2][0] = { 0, 0, 0}; out[2][1] = { 0, sign_[2], 0}; out[2][2] = { 0, 0, 0}; out[3][0] = { 0, 0, 0}; out[3][1] = { 0, sign_[3], 0}; out[3][2] = { 0, 0, 0}; out[4][0] = { 0, 0, 0}; out[4][1] = { 0, 0, 0}; out[4][2] = { 0, 0, sign_[4]}; out[5][0] = { 0, 0, 0}; out[5][1] = { 0, 0, 0}; out[5][2] = { 0, 0, sign_[5]}; out[6][0] = { 6*in[1]-3, 6*in[0]-6, 0}; out[6][1] = { 0, -6*in[1]+3, 0}; out[6][2] = { 0, 0, 0}; out[7][0] = {-6*in[1]+3, -6*in[0], 0}; out[7][1] = { 0, 6*in[1]-3, 0}; out[7][2] = { 0, 0, 0}; out[8][0] = { 6*in[0]-3, 0, 0}; out[8][1] = {-6*in[1]+6, -6*in[0]+3, 0}; out[8][2] = { 0, 0, 0}; out[9][0] = {-6*in[0]+3, 0, 0}; out[9][1] = { 6*in[1], 6*in[0]-3, 0}; out[9][2] = { 0, 0, 0}; out[10][0] = {-6*in[0]+3, 0, 0}; out[10][1] = { 0, 0, 0}; out[10][2] = { 6*in[2]-6, 0, 6*in[0]-3}; out[11][0] = { 6*in[0]-3, 0, 0}; out[11][1] = { 0, 0, 0}; out[11][2] = { -6*in[2], 0, -6*in[0]+3}; out[12][0] = {-6*in[2]+3, 0, -6*in[0]+6}; out[12][1] = { 0, 0, 0}; out[12][2] = { 0, 0, 6*in[2]-3}; out[13][0] = { 6*in[2]-3, 0, 6*in[0]}; out[13][1] = { 0, 0, 0}; out[13][2] = { 0, 0, -6*in[2]+3}; out[14][0] = { 0, 0, 0}; out[14][1] = { 0, 6*in[2]-3, 6*in[1]-6}; out[14][2] = { 0, 0, -6*in[2]+3}; out[15][0] = { 0, 0, 0}; out[15][1] = { 0, -6*in[2]+3, -6*in[1]}; out[15][2] = { 0, 0, 6*in[2]-3}; out[16][0] = { 0, 0, 0}; out[16][1] = { 0, 6*in[1]-3, 0}; out[16][2] = { 0, -6*in[2]+6, -6*in[1]+3}; out[17][0] = { 0, 0, 0}; out[17][1] = { 0, -6*in[1]+3, 0}; out[17][2] = { 0, 6*in[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] = { sign_[0], 0, 0}; out[1] = { sign_[1], 0, 0}; out[2] = { 0, 0, 0}; out[3] = { 0, 0, 0}; out[4] = { 0, 0, 0}; out[5] = { 0, 0, 0}; out[6] = { 6*in[1]-3, 0, 0}; out[7] = {-6*in[1]+3, 0, 0}; out[8] = { 6*in[0]-3, -6*in[1]+6, 0}; out[9] = {-6*in[0]+3, 6*in[1], 0}; out[10] = {-6*in[0]+3, 0, 6*in[2]-6}; out[11] = { 6*in[0]-3, 0, -6*in[2]}; out[12] = {-6*in[2]+3, 0, 0}; out[13] = { 6*in[2]-3, 0, 0}; out[14] = { 0, 0, 0}; out[15] = { 0, 0, 0}; out[16] = { 0, 0, 0}; out[17] = { 0, 0, 0}; break; case 1: out[0] = { 0, 0, 0}; out[1] = { 0, 0, 0}; out[2] = { 0, sign_[2], 0}; out[3] = { 0, sign_[3], 0}; out[4] = { 0, 0, 0}; out[5] = { 0, 0, 0}; out[6] = { 6*in[0]-6, -6*in[1]+3, 0}; out[7] = { -6*in[0], 6*in[1]-3, 0}; out[8] = { 0, -6*in[0]+3, 0}; out[9] = { 0, 6*in[0]-3, 0}; out[10] = { 0, 0, 0}; out[11] = { 0, 0, 0}; out[12] = { 0, 0, 0}; out[13] = { 0, 0, 0}; out[14] = { 0, 6*in[2]-3, 0}; out[15] = { 0, -6*in[2]+3, 0}; out[16] = { 0, 6*in[1]-3, -6*in[2]+6}; out[17] = { 0, -6*in[1]+3, 6*in[2]}; break; case 2: out[0] = { 0, 0, 0}; out[1] = { 0, 0, 0}; out[2] = { 0, 0, 0}; out[3] = { 0, 0, 0}; out[4] = { 0, 0, sign_[4]}; out[5] = { 0, 0, sign_[5]}; out[6] = { 0, 0, 0}; out[7] = { 0, 0, 0}; out[8] = { 0, 0, 0}; out[9] = { 0, 0, 0}; out[10] = { 0, 0, 6*in[0]-3}; out[11] = { 0, 0, -6*in[0]+3}; out[12] = {-6*in[0]+6, 0, 6*in[2]-3}; out[13] = { 6*in[0], 0, -6*in[2]+3}; out[14] = { 0, 6*in[1]-6, -6*in[2]+3}; out[15] = { 0, -6*in[1], 6*in[2]-3}; out[16] = { 0, 0, -6*in[1]+3}; out[17] = { 0, 0, 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.hh000066400000000000000000000022761411343327200440730ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000057611411343327200443230ustar00rootroot00000000000000dune-localfunctions-2.8.0/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; 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(GeometryTypes::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.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d.hh000077500000000000000000000043561411343327200340700ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ BDM1Simplex2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::triangle; } private: BDM1Simplex2DLocalBasis basis; BDM1Simplex2DLocalCoefficients coefficients; BDM1Simplex2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI1_SIMPLEX2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d/000077500000000000000000000000001411343327200335345ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004251411343327200362160ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2dinstall(FILES brezzidouglasmarini1simplex2dlocalbasis.hh brezzidouglasmarini1simplex2dlocalcoefficients.hh brezzidouglasmarini1simplex2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d) brezzidouglasmarini1simplex2dlocalbasis.hh000077500000000000000000000115341411343327200440370ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000077500000000000000000000022171411343327200453750ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000077500000000000000000000066361411343327200456340ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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) { using std::sqrt; 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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, std::vector& out) const { // f gives v*outer normal at a point on the edge! typedef typename LB::Traits::RangeFieldType Scalar; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(6); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const Dune::QuadratureRule& rule = Dune::QuadratureRules::rule(Dune::GeometryTypes::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; auto y = f(localPos); 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; y = f(localPos); 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; y = f(localPos); 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.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d.hh000066400000000000000000000042751411343327200333230ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < ?? * * \param s Edge orientation indicator */ BDM2Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::quadrilateral; } private: BDM2Cube2DLocalBasis basis; BDM2Cube2DLocalCoefficients coefficients; BDM2Cube2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_QUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d/000077500000000000000000000000001411343327200327725ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004111411343327200354470ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2dinstall(FILES brezzidouglasmarini2cube2dlocalbasis.hh brezzidouglasmarini2cube2dlocalcoefficients.hh brezzidouglasmarini2cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d) brezzidouglasmarini2cube2dlocalbasis.hh000066400000000000000000000247511411343327200425350ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000024161411343327200440670ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000104331411343327200443130ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate(const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(14); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const QuadratureRule& rule = QuadratureRules::rule(GeometryTypes::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; auto y = f(localPos); 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; y = f(localPos); 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; y = f(localPos); 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; y = f(localPos); 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(GeometryTypes::cube(2), qOrder); for (typename QuadratureRule::const_iterator it=rule2.begin(); it!=rule2.end(); ++it) { auto y = f(it->position()); 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.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d.hh000066400000000000000000000043561411343327200340660ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ BDM2Simplex2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::triangle; } private: BDM2Simplex2DLocalBasis basis; BDM2Simplex2DLocalCoefficients coefficients; BDM2Simplex2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI2_SIMPLEX2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d/000077500000000000000000000000001411343327200335355ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000004251411343327200362170ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2dinstall(FILES brezzidouglasmarini2simplex2dlocalbasis.hh brezzidouglasmarini2simplex2dlocalcoefficients.hh brezzidouglasmarini2simplex2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d) brezzidouglasmarini2simplex2dlocalbasis.hh000066400000000000000000000220671411343327200440410ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000025641411343327200454010ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000110401411343327200456140ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate(const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(12); fill(out.begin(), out.end(), 0.0); const int qOrder = 4; const Dune::QuadratureRule& rule = Dune::QuadratureRules::rule(Dune::GeometryTypes::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; auto y = f(localPos); 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; y = f(localPos); 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; y = f(localPos); 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(GeometryTypes::simplex(2), qOrder); for (typename QuadratureRule::const_iterator it=rule2.begin(); it!=rule2.end(); ++it) { typename LB::Traits::DomainType localPos = it->position(); auto y = f(localPos); 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.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarinicube.hh000066400000000000000000000057471411343327200330200ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_BREZZIDOUGLASMARINICUBE_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_BREZZIDOUGLASMARINICUBE_HH #include #include #include namespace Dune { /** * \brief Brezzi-Douglas-Marini local finite element for cubes * * \tparam D Number type to represent domain coordinates * \tparam R Number type to represent shape function values * \tparam dim Dimension of the reference elements, must be 2 or 3 * \tparam order Polynomial order of the element */ template class BrezziDouglasMariniCubeLocalFiniteElement; /** * \brief Brezzi-Douglas-Marini local finite elements for cubes with dimension 2 and order 1. */ template class BrezziDouglasMariniCubeLocalFiniteElement : public BDM1Cube2DLocalFiniteElement { public: /** \brief Default constructor */ BrezziDouglasMariniCubeLocalFiniteElement() {} /** * \brief Constructor with a set of edge orientations * * \param s Bitfield of size 4 giving the orientations of the four element edges */ BrezziDouglasMariniCubeLocalFiniteElement(int s) : BDM1Cube2DLocalFiniteElement::BDM1Cube2DLocalFiniteElement(s) {} }; /** * \brief Brezzi-Douglas-Marini local finite elements for cubes with dimension 2 and order 2. */ template class BrezziDouglasMariniCubeLocalFiniteElement : public BDM2Cube2DLocalFiniteElement { public: /** \brief Default constructor */ BrezziDouglasMariniCubeLocalFiniteElement() {} /** * \brief Constructor with a set of edge orientations * * \param s Bitfield of size 4 giving the orientations of the four element edges */ BrezziDouglasMariniCubeLocalFiniteElement(int s) : BDM2Cube2DLocalFiniteElement::BDM2Cube2DLocalFiniteElement(s) {} }; /** * \brief Brezzi-Douglas-Marini local finite elements for cubes with dimension 3 and order 1. */ template class BrezziDouglasMariniCubeLocalFiniteElement : public BDM1Cube3DLocalFiniteElement { public: /** \brief Default constructor */ BrezziDouglasMariniCubeLocalFiniteElement() {} /** * \brief Constructor with a set of edge orientations * * \param s Bitfield of size 6 giving the orientations of the six element facets */ BrezziDouglasMariniCubeLocalFiniteElement(int s) : BDM1Cube3DLocalFiniteElement::BDM1Cube3DLocalFiniteElement(s) {} }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_BREZZIDOUGLASMARINICUBE_HH dune-localfunctions-2.8.0/dune/localfunctions/brezzidouglasmarini/brezzidouglasmarinisimplex.hh000066400000000000000000000045221411343327200335510ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_BREZZIDOUGLASMARINISIMPLEX_HH #define DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_BREZZIDOUGLASMARINISIMPLEX_HH #include #include namespace Dune { /** * \brief Brezzi-Douglas-Marini local finite element for simplices * * \tparam D Number type to represent domain coordinates * \tparam R Number type to represent shape function values * \tparam dim Dimension of the reference elements, currently only 2 is supported * \tparam order Polynomial order of the element */ template class BrezziDouglasMariniSimplexLocalFiniteElement; /** * \brief Brezzi-Douglas-Marini local finite elements for simplices with dimension 2 and order 1. */ template class BrezziDouglasMariniSimplexLocalFiniteElement : public BDM1Simplex2DLocalFiniteElement { public: /** \brief Default constructor */ BrezziDouglasMariniSimplexLocalFiniteElement() {} /** * \brief Constructor with a set of edge orientations * * \param s Bitfield of size 3 giving the orientations of the three element edges */ BrezziDouglasMariniSimplexLocalFiniteElement(int s) : BDM1Simplex2DLocalFiniteElement::BDM1Simplex2DLocalFiniteElement(s) {} }; /** * \brief Brezzi-Douglas-Marini local finite elements for simplices with dimension 2 and order 2. */ template class BrezziDouglasMariniSimplexLocalFiniteElement : public BDM2Simplex2DLocalFiniteElement { public: /** \brief Default constructor */ BrezziDouglasMariniSimplexLocalFiniteElement() {} /** * \brief Constructor with a set of edge orientations * * \param s Bitfield of size 3 giving the orientations of the three element edges */ BrezziDouglasMariniSimplexLocalFiniteElement(int s) : BDM2Simplex2DLocalFiniteElement::BDM2Simplex2DLocalFiniteElement(s) {} }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_BREZZIDOUGLASMARINI_BREZZIDOUGLASMARINISIMPLEX_HH dune-localfunctions-2.8.0/dune/localfunctions/common/000077500000000000000000000000001411343327200227435ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/common/CMakeLists.txt000066400000000000000000000005251411343327200255050ustar00rootroot00000000000000install(FILES interface.hh interfaceswitch.hh localbasis.hh localinterpolation.hh localkey.hh localfiniteelementtraits.hh localfiniteelementvariant.hh localfiniteelementvariantcache.hh localtoglobaladaptors.hh virtualinterface.hh virtualwrappers.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/common) dune-localfunctions-2.8.0/dune/localfunctions/common/interface.hh000066400000000000000000000237211411343327200252310ustar00rootroot00000000000000// -*- 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 DomainFieldType; //! \brief Enum for domain dimension enum { //! \brief dimension of the domain dimDomain = implementationDefined }; //! Type used for coordinate vectors in the domain typedef ImplementationDefined DomainType; //! \} //! \name Range properties (global range only) //! \{ //! Field type of the range typedef ImplementationDefined RangeFieldType; //! \brief Enum for range dimension enum { //! \brief dimension of the range dimRange = implementationDefined }; //! Type used for range values typedef ImplementationDefined RangeType; //! \} //! Jacobian properties /** * \note The Jacobian should be some matrix type with \c dimRange x * \c dimDomain components of type \c RangeFieldType. */ typedef ImplementationDefined Jacobian; }; //! 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::DomainType& in, std::vector& out) const; //! Evaluate Jacobian of all shape functions at given position void evaluateJacobian(const Traits::DomainType& in, std::vector& out) const; /** \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; }; //! 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.8.0/dune/localfunctions/common/interfaceswitch.hh000066400000000000000000000236611411343327200264560ustar00rootroot00000000000000// -*- 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 #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 (as a shared pointer) * a finite element and update that pointer while iterating * through the grid. This works well as long as there is only a * moderate number of different finite elements, which can be * stored somewhere and don't change for the duration of the * algorithm. This is the case for most local finite elements, * since they exists in a finite number of variants. * * If the number of possible finite element realizations grows to * big, e.g. for global finite elements or also for p-adaptive * local finite elements, these are only created on the * fly. Therefore we need to store a copy. Since finite elements * in general are not assignable, we either copy-construct or * move-construt them for each grid element we visit. * * To accommodate both interfaces, we store in a `shared_ptr`. * Different ways to initialize a possible, from an l-value * reference, an r-value reference or from a shared_ptr. * * For backwards compatibility we assume that an l-value reference * to a local finite element is persistent and that we can simply * store the pointer using `stackobject_to_shared_ptr`, while in * the case of global finite elements we always need to copy * construct using `make_shared`. If a local finite element is not * persistent, it should be passed in as an r-value * reference. 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 = std::make_shared(fe); } //! Store a finite element in the store. static void setStore(Store& store, FiniteElement&& fe) { store = std::make_shared(std::move(fe)); } //! Store a finite element in the store. static void setStore(Store& store, const Store& fe) { store = 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 std::shared_ptr Store; //! Store a finite element in the store. static void setStore(Store& store, const FiniteElement& fe) { store = stackobject_to_shared_ptr(fe); } //! Store a finite element in the store. static void setStore(Store& store, FiniteElement&& fe) { store = std::make_shared(std::move(fe)); } //! Store a finite element in the store. static void setStore(Store& store, const Store& 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; //! 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; //! 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.8.0/dune/localfunctions/common/localbasis.hh000066400000000000000000000037551411343327200254120ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_COMMON_LOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_COMMON_LOCALBASIS_HH 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. \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; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/common/localfiniteelementtraits.hh000066400000000000000000000010401411343327200303510ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/common/localfiniteelementvariant.hh000066400000000000000000000316251411343327200305230ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_COMMON_LOCALFINITEELEMENTVARIANT_HH #define DUNE_LOCALFUNCTIONS_COMMON_LOCALFINITEELEMENTVARIANT_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Impl { // Helper for visiting a variant containing monostate. // Since a generic lambda will in most cases not compile // for monostate, we add special empty overloads for monostate. // Hence visitIf will simply do nothing in the case of a // monostate value. template void visitIf(Visitor&& visitor, Variant&& variant) { auto visitorWithFallback = overload([&](std::monostate& impl) {}, [&](const std::monostate& impl) {}, visitor); std::visit(visitorWithFallback, variant); } template class LocalBasisVariant { template struct FirstType { using type = I0; }; using FirstImpTraits = typename FirstType::type::Traits; public: // We do not simply copy Implementation::LocalBasisTraits because this // may be implementation specific. To stay clean, we simply put all its // data into the default LocalBasisTraits. using Traits = typename Dune::LocalBasisTraits< typename FirstImpTraits::DomainFieldType, FirstImpTraits::dimDomain, typename FirstImpTraits::DomainType, typename FirstImpTraits::RangeFieldType, FirstImpTraits::dimRange, typename FirstImpTraits::RangeType, typename FirstImpTraits::JacobianType>; template LocalBasisVariant(const Implementation& impl) : impl_(&impl), size_(impl.size()), order_(impl.order()) {} LocalBasisVariant() = default; LocalBasisVariant(const LocalBasisVariant& other) = default; LocalBasisVariant(LocalBasisVariant&& other) = default; LocalBasisVariant& operator=(const LocalBasisVariant& other) = default; LocalBasisVariant& operator=(LocalBasisVariant&& other) = default; /** * \brief Number of shape functions */ unsigned int size() const { return size_; } /** * \brief Polynomial order of the shape functions */ unsigned int order() const { return order_; } /** * \brief Evaluate all shape functions */ inline void evaluateFunction( const typename Traits::DomainType& x, std::vector& out) const { Impl::visitIf([&](const auto* impl) { impl->evaluateFunction(x, out); }, impl_); } /** * \brief Evaluate Jacobian of all shape functions */ inline void evaluateJacobian( const typename Traits::DomainType& x, std::vector& out) const { Impl::visitIf([&](const auto* impl) { impl->evaluateJacobian(x, out); }, impl_); } /** * \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 x 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& x, std::vector& out) const { Impl::visitIf([&](const auto* impl) { impl->partial(order, x, out); }, impl_); } private: std::variant impl_; std::size_t size_; std::size_t order_; }; template class LocalCoefficientsVariant { public: template LocalCoefficientsVariant(const Implementation& impl) : impl_(&impl), size_(impl.size()) {} LocalCoefficientsVariant() = default; LocalCoefficientsVariant(const LocalCoefficientsVariant& other) = default; LocalCoefficientsVariant(LocalCoefficientsVariant&& other) = default; LocalCoefficientsVariant& operator=(const LocalCoefficientsVariant& other) = default; LocalCoefficientsVariant& operator=(LocalCoefficientsVariant&& other) = default; /** * \brief Number of shape functions */ unsigned int size() const { return size_; } const Dune::LocalKey& localKey (std::size_t i) const { // We can't use visitIf since we have to return something // even for a monostate value. Since the return type is // an l-value reference, we use a default constructed // dummy LocalKey value. static const Dune::LocalKey dummyLocalKey; return std::visit(overload( [&](const std::monostate& impl) -> decltype(auto) { return (dummyLocalKey);}, [&](const auto* impl) -> decltype(auto) { return impl->localKey(i); }), impl_); } private: std::variant impl_; std::size_t size_; }; template class LocalInterpolationVariant { public: template LocalInterpolationVariant(const Implementation& impl) : impl_(&impl) {} LocalInterpolationVariant() = default; LocalInterpolationVariant(const LocalInterpolationVariant& other) = default; LocalInterpolationVariant(LocalInterpolationVariant&& other) = default; LocalInterpolationVariant& operator=(const LocalInterpolationVariant& other) = default; LocalInterpolationVariant& operator=(LocalInterpolationVariant&& other) = default; template void interpolate (const F& ff, std::vector& out) const { Impl::visitIf([&](const auto* impl) { impl->interpolate(ff, out); }, impl_); } private: std::variant impl_; }; } // namespace Impl /** * \brief Type erasure class for wrapping LocalFiniteElement classes * * This is a type erasure wrapper class for types implementing the * LocalFiniteElement interface. The types of the LocalFiniteElement * implementations that this class can hold have to be provided as * template parameter. * * The implementation is based on std::variant. * Notice that this prepends std::monostate to the Implementations * list for the internally stored std::variant such that * LocalFiniteElementVariant can be empty and is default-constructible. * As a consequence providing std::monostate manually to * LocalFiniteElementVariant is neither necessary nor allowed. * Access to the stored implementation is internally implemented * using std::visit(). To avoid multiple trivial std::visit() * calls, the results of size(), order(), and type() are cached * on creation and assignment. * * In empty state accessing any method beyond operator bool(), variant(), * or assignment leads to undefined behavior. * * The LocalBasisTraits are extracted from the implementation * provided as first template parameter. The other implementations are * required to be compatible with this one. * * \tparam Implementations List of supported LocalFiniteElement implementations */ template class LocalFiniteElementVariant { // In each LocalFooVariant we store a std::variant, i.e. a std::variant // with the pointer to the Foo implementation unless LocalFiniteElementVariant stores a monostate. In this // case each LocalFooVariant also stores a monostate (and not a monostate*). using LocalBasis = Impl::LocalBasisVariant; using LocalCoefficients = Impl::LocalCoefficientsVariant; using LocalInterpolation = Impl::LocalInterpolationVariant; // Update members after changing impl_ void updateMembers() { std::visit(overload( [&](std::monostate&) { localBasis_ = LocalBasis(); localCoefficients_ = LocalCoefficients(); localInterpolation_ = LocalInterpolation(); size_ = 0; geometryType_ = GeometryType{}; }, [&](auto&& impl) { localBasis_ = LocalBasis(impl.localBasis()); localCoefficients_ = LocalCoefficients(impl.localCoefficients()); localInterpolation_ = LocalInterpolation(impl.localInterpolation()); size_ = impl.size(); geometryType_ = impl.type(); }), impl_); } public: /** * \brief Export LocalFiniteElementTraits */ using Traits = typename Dune::LocalFiniteElementTraits; /** * \brief Construct empty LocalFiniteElementVariant */ LocalFiniteElementVariant() = default; /** * \brief Construct empty LocalFiniteElementVariant */ LocalFiniteElementVariant(const std::monostate& monostate) {} /** * \brief Construct LocalFiniteElementVariant * * The created LocalFiniteElementVariant will store a * copy of the provided implementation. */ template, Implementations>...>::value, int> = 0> LocalFiniteElementVariant(Implementation&& impl) : impl_(std::forward(impl)) { updateMembers(); } /** * \brief Copy constructor */ LocalFiniteElementVariant(const LocalFiniteElementVariant& other) : impl_(other.impl_) { updateMembers(); } /** * \brief Move constructor */ LocalFiniteElementVariant(LocalFiniteElementVariant&& other) : impl_(std::move(other.impl_)) { updateMembers(); } /** * \brief Copy assignment */ LocalFiniteElementVariant& operator=(const LocalFiniteElementVariant& other) { impl_ = other.impl_; updateMembers(); return *this; } /** * \brief Move assignment */ LocalFiniteElementVariant& operator=(LocalFiniteElementVariant&& other) { impl_ = std::move(other.impl_); updateMembers(); return *this; } /** * \brief Assignment from implementation */ template, Implementations>...>::value, int> = 0> LocalFiniteElementVariant& operator=(Implementation&& impl) { impl_ = std::forward(impl); updateMembers(); return *this; } /** * \brief Provide access to LocalBasis implementation of this LocalFiniteElement */ const typename Traits::LocalBasisType& localBasis() const { return localBasis_; } /** * \brief Provide access to LocalCoefficients implementation of this LocalFiniteElement */ const typename Traits::LocalCoefficientsType& localCoefficients() const { return localCoefficients_; } /** * \brief Provide access to LocalInterpolation implementation of this LocalFiniteElement */ const typename Traits::LocalInterpolationType& localInterpolation() const { return localInterpolation_; } /** * \brief Number of shape functions */ unsigned int size() const { return size_; } /** * \brief Number of shape functions */ constexpr GeometryType type() const { return geometryType_; } /** * \brief Provide access to underlying std::variant * * This allows to use std::visit on a higher level * which allows to avoid the indirection of the * std::variant - polymorphism inside the visitor code. * Notice that the provided std::variant contains * std::monostate in its type list. Hence any * visitor used to access the variant has to be * std::monostate-aware. */ const auto& variant() const { return impl_; } /** * \brief Check if LocalFiniteElementVariant stores an implementation * * This returns true iff variant() does not store a monostate. */ operator bool () const { return not(std::holds_alternative(variant())); } private: std::variant impl_; std::size_t size_; GeometryType geometryType_; LocalBasis localBasis_; LocalCoefficients localCoefficients_; LocalInterpolation localInterpolation_; }; } // end namespace Dune #endif // DUNE_LOCALFUNCTIONS_COMMON_LOCALFINITEELEMENTVARIANT_HH dune-localfunctions-2.8.0/dune/localfunctions/common/localfiniteelementvariantcache.hh000066400000000000000000000111741411343327200315040ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_COMMON_LOCALFINITEELEMENTVARIANTCACHE_HH #define DUNE_LOCALFUNCTIONS_COMMON_LOCALFINITEELEMENTVARIANTCACHE_HH #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Impl { // This class provides the index method of LocalGeometryTypeIndex // but throws a Dune::RangeError if the dimension does not match. // This can be helpful to catch errors in a LocalFiniteElementVariantCache // instance based on dimension specific GeometryType indices. template struct FixedDimLocalGeometryTypeIndex { inline static std::size_t index(const GeometryType >) { if (gt.dim() != dim) DUNE_THROW(Dune::RangeError, "Asking for dim=" << dim << " specific index of GeometryType with dimension " << gt.dim()); return LocalGeometryTypeIndex::index(gt); } }; } // end namespace Impl /** \brief A cache storing a compile time selection of local finite element implementations * * This class stores a compile time selection of LocalFiniteElement implementations. * The exported FiniteElementType is a LocalFiniteElementVariant. * * The base class is required to implement two methods: getImplementations() and index(). * The index(key...) method computes an index that uniquely identifies a LocalFiniteElement * implementation for the provided key data. * The getImplementations() method returns a std::tuple with one entry for each * LocalFiniteElement implementation. Each entry is an std::pair consisting of the * index of the implementation and a callable object that creates a corresponding * LocalFiniteElement implementation. * * The constructor forwards all arguments to the base class. * * For performence reasons all LocalFiniteElement implementations are created * during construction and stored in an std::vector according to the associated * indices. Hence densly packed indices should be prefered to avoid wasting space * for emplty LocalFiniteElementVariant's string no implementation. * * \tparam Base Type of the base class providing getImplementations() and index(). */ template class LocalFiniteElementVariantCache : Base { template struct GenerateLFEVariant; template struct GenerateLFEVariant...>> { using type = UniqueTypes_t()())...>; }; using Base::getImplementations; using Base::index; using Implementations = decltype(std::declval().getImplementations()); public: /** * \brief Type of exported LocalFiniteElement's * * This is a LocalFiniteElementVariant * with Implementations... being the list of all provided * implementations. */ using FiniteElementType = typename GenerateLFEVariant::type; /** \brief Default constructor * * Prefills the cache with all implementations. */ template LocalFiniteElementVariantCache(Args&&... args) : Base(std::forward(args)...) { Dune::Hybrid::forEach(getImplementations(), [&,this](auto feImpl) { auto implIndex = feImpl.first; if (cache_.size() < implIndex+1) cache_.resize(implIndex+1); cache_[implIndex] = feImpl.second(); }); } /** \brief Copy constructor */ LocalFiniteElementVariantCache(const LocalFiniteElementVariantCache& other) = default; /** \brief Move constructor */ LocalFiniteElementVariantCache(LocalFiniteElementVariantCache&& other) = default; /** \brief Get the LocalFiniteElement for the given key data * * \throws Dune::RangeError If the cache doesn't hold a value matching the requested type. */ template const auto& get(const Key&... key) const { auto implIndex = index(key...); if (implIndex >= cache_.size()) DUNE_THROW(Dune::RangeError,"There is no LocalFiniteElement of the requested type."); if (not(cache_[implIndex])) DUNE_THROW(Dune::RangeError,"There is no LocalFiniteElement of the requested type."); return cache_[implIndex]; } private: std::vector cache_; }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_COMMON_LOCALFINITEELEMENTVARIANT_HH dune-localfunctions-2.8.0/dune/localfunctions/common/localinterpolation.hh000066400000000000000000000035451411343327200271750ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_COMMON_LOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_COMMON_LOCALINTERPOLATION_HH #include #include namespace Dune { namespace Impl { // Concept for function supporting f.evaluate(Domain, Range&) template struct FunctionWithEvaluate { template auto require(F&& f) -> decltype( f.evaluate(std::declval(), std::declval()) ); }; // Concept for function supporting f(Domain) template struct FunctionWithCallOperator { template auto require(F&& f) -> decltype( f(std::declval()) ); }; // Create function supporting Range = f(Domain) // If the argument already does this, just forward it. template, F>(), int> = 0> decltype(auto) makeFunctionWithCallOperator(const F& f) { return f; } // Create function supporting Range = f(Domain) // If the argument does not support this, wrap it in a lambda template >, F>(), int> = 0> #ifndef DUNE_DEPRECATED_INTERPOLATE_CHECK [[deprecated( "Passing functions only supporting 'f.evaluate(x,y)' to interpolate() is deprecated." "Use functions supporting operator(), i.e. f(x) instead!")]] #endif decltype(auto) makeFunctionWithCallOperator(const F& f) { return [&](auto&& x) { typename std::decay_t::Traits::RangeType y; f.evaluate(x,y); return y; }; } } // namespace Impl } // namespace Dune #endif dune-localfunctions-2.8.0/dune/localfunctions/common/localkey.hh000066400000000000000000000054771411343327200251040ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/common/localtoglobaladaptors.hh000066400000000000000000000254241411343327200276470ustar00rootroot00000000000000// -*- 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; }; //! 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.8.0/dune/localfunctions/common/virtualinterface.hh000066400000000000000000000246121411343327200266400ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_COMMON_VIRTUALINTERFACE_HH #define DUNE_LOCALFUNCTIONS_COMMON_VIRTUALINTERFACE_HH #include #include #include #include #include #include #include #include #include namespace Dune { // forward declaration needed by the helper traits template class LocalInterpolationVirtualInterface; // ----------------------------------------------------------------- // Helper traits classes // ----------------------------------------------------------------- /** * @brief Return a proper base class for functions to use with LocalInterpolation. * * @tparam FE A FiniteElement type * * \deprecated * This class is deprecated. * To keep this traits class working it exports a simple * look-a-like of the old Dune::Function base class. * However, you should stop using this and pass functions with * plain operator() interface to interpolate() from now on. */ template class [[deprecated("Dune::LocalFiniteElementFunctionBase is deprecated after Dune 2.7. You can now pass functions providing operator() to interpolate.")]] LocalFiniteElementFunctionBase { typedef typename FE::Traits::LocalBasisType::Traits::DomainType Domain; typedef typename FE::Traits::LocalBasisType::Traits::RangeType Range; // Hack: Keep a copy of Dune::Function here. This allows to avoid depending // on the deprecated dune-common header while still keeping the LocalFiniteElementFunctionBase // mechanism working during its deprecation period. class FunctionBaseDummy { public: using RangeType = Range; using DomainType = Domain; struct Traits { using RangeType = Range; using DomainType = Domain; }; void evaluate(const DomainType& x, RangeType& y) const; }; public: using VirtualFunctionBase = FunctionBaseDummy; using FunctionBase = FunctionBaseDummy; /** \brief Base class type for functions to use with LocalInterpolation * * This is just a dummy providing the old typedefs. * interface and Function base class otherwise. */ using type = FunctionBaseDummy; }; // ----------------------------------------------------------------- // Basis // ----------------------------------------------------------------- /** * @brief virtual base class for a local basis * * Provides the local basis interface with pure virtual methods. * This class defines the interface using pure virtual methods. */ template class LocalBasisVirtualInterface { public: using Traits = T; virtual ~LocalBasisVirtualInterface() {} //! \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; }; // ----------------------------------------------------------------- // 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 function to interpolate using FunctionType = std::function; //! 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 function to interpolate using FunctionType = std::function; //! type of the coefficient vector in the interpolate method typedef typename RangeType::field_type CoefficientType; virtual ~LocalInterpolationVirtualInterface() {} // This method is only noted 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; /** \brief determine coefficients interpolating a given function * * \param[in] ff Function instance used to interpolate. * \param[out] out Resulting coefficients vector. */ template::value, int> = 0> void interpolate (const F& ff, std::vector& out) const { const auto& f = Impl::makeFunctionWithCallOperator(ff); const LocalInterpolationVirtualInterfaceBase& asBase = *this; asBase.interpolate(FunctionType(std::cref(f)),out); } /** \brief determine coefficients interpolating a given function * * \param[in] ff Function instance used to interpolate. * \param[out] out Resulting coefficients vector. */ template void interpolate (const F& ff, std::vector& out) const { const auto& f = Impl::makeFunctionWithCallOperator(ff); std::vector outDummy; const LocalInterpolationVirtualInterfaceBase& asBase = *this; asBase.interpolate(FunctionType(std::cref(f)),outDummy); out.resize(outDummy.size()); for(typename std::vector::size_type i=0; i class LocalFiniteElementVirtualInterface { using LocalBasisTraits = T; public: typedef LocalFiniteElementTraits< LocalBasisVirtualInterface, LocalCoefficientsVirtualInterface, LocalInterpolationVirtualInterface< typename LocalBasisTraits::DomainType, typename LocalBasisTraits::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.8.0/dune/localfunctions/common/virtualwrappers.hh000066400000000000000000000223761411343327200265500ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_COMMON_VIRTUALWRAPPERS_HH #define DUNE_LOCALFUNCTIONS_COMMON_VIRTUALWRAPPERS_HH #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 * * @tparam T The LocalBasisTraits class * @tparam Imp LocalBasisInterface implementation */ template class LocalBasisVirtualImp : public LocalBasisVirtualInterface { template friend class LocalFiniteElementVirtualImp; protected: //! constructor taking an implementation of the interface LocalBasisVirtualImp( const Imp &imp ) : impl_(imp) {} public: using Traits = T; //! @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); } protected: const Imp& impl_; }; // ----------------------------------------------------------------- // Interpolation // ----------------------------------------------------------------- /** * @brief class for wrapping a local interpolation * using the virtual interface * * @tparam DomainType domain type of the function to interpolate * @tparam RangeType range type of the function 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 LocalFiniteElementVirtualInterface { using LocalBasisTraits = typename Imp::Traits::LocalBasisType::Traits; using Interface = LocalFiniteElementVirtualInterface; 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_; const LocalBasisVirtualImp localBasisImp_; const LocalCoefficientsVirtualImp localCoefficientsImp_; const LocalInterpolationVirtualImp localInterpolationImp_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/crouzeixraviart.hh000066400000000000000000000160161411343327200252410ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_CROUZEIXRAVIART_HH #define DUNE_LOCALFUNCTIONS_CROUZEIXRAVIART_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Impl { /** \brief Crouzeix-Raviart element on the reference simplex \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 domain simplex */ template class CrouzeixRaviartLocalBasis { public: using Traits = LocalBasisTraits,R,1,FieldVector,FieldMatrix >; /** \brief Number of shape functions -- one for each simplex facet */ static constexpr unsigned int size () { return dim+1; } //! \brief Evaluate all shape functions void evaluateFunction(const typename Traits::DomainType& x, std::vector& out) const { out.resize(size()); std::fill(out.begin(), out.end()-1, 1.0); out.back() = 1.0-dim; for (unsigned int i=0; i& out) const { out.resize(size()); for (unsigned i=0; i& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); out.resize(size()); if (totalOrder == 0) { evaluateFunction(in, out); return; } if (totalOrder==1) { auto direction = std::find(order.begin(), order.end(), 1)-order.begin(); for (unsigned int i=0; i class CrouzeixRaviartLocalCoefficients { public: //! \brief Default constructor CrouzeixRaviartLocalCoefficients () : localKeys_(size()) { for (std::size_t i=0; i localKeys_; }; /** \brief Evaluate the degrees of freedom of a Crouzeix-Raviart basis * * \tparam LocalBasis The corresponding set of shape functions */ template class CrouzeixRaviartLocalInterpolation { public: /** \brief Evaluate a given function at the facet midpoints * * \tparam F Type of function to evaluate * \tparam C Type used for the values of the function * \param[in] ff Function to evaluate * \param[out] out Array of function values */ template void interpolate (const F& ff, std::vector& out) const { constexpr auto dim = LocalBasis::Traits::dimDomain; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(LocalBasis::size()); // Evaluate at the facet midpoints auto refSimplex = ReferenceElements::simplex(); for (int i=0; i(i).center()); } }; } } // namespace Dune::Impl namespace Dune { /** \brief Crouzeix-Raviart finite element * * \tparam D type used for domain coordinates * \tparam R type used for function values * \tparam dim dimension of the reference element */ template class CrouzeixRaviartLocalFiniteElement { public: /** \brief Export number types, dimensions, etc. */ using Traits = LocalFiniteElementTraits, Impl::CrouzeixRaviartLocalCoefficients, Impl::CrouzeixRaviartLocalInterpolation > >; /** \brief Returns the local basis, i.e., the set of shape functions */ const typename Traits::LocalBasisType& localBasis() const { return basis_; } /** \brief Returns the assignment of the degrees of freedom to the element subentities */ const typename Traits::LocalCoefficientsType& localCoefficients() const { return coefficients_; } /** \brief Returns object that evaluates degrees of freedom */ const typename Traits::LocalInterpolationType& localInterpolation() const { return interpolation_; } /** \brief The number of shape functions */ static constexpr std::size_t size() { return dim+1; } /** \brief The reference element that the local finite element is defined on */ static constexpr GeometryType type() { return GeometryTypes::simplex(dim); } private: Impl::CrouzeixRaviartLocalBasis basis_; Impl::CrouzeixRaviartLocalCoefficients coefficients_; Impl::CrouzeixRaviartLocalInterpolation > interpolation_; }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_CROUZEIXRAVIART_HH dune-localfunctions-2.8.0/dune/localfunctions/dualmortarbasis.hh000066400000000000000000000005541411343327200251740ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/dualmortarbasis/000077500000000000000000000000001411343327200246475ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/dualmortarbasis/CMakeLists.txt000066400000000000000000000003231411343327200274050ustar00rootroot00000000000000add_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.8.0/dune/localfunctions/dualmortarbasis/dualp1.hh000066400000000000000000000045041411343327200263610ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_DUALMORTARBASIS_DUALP1_HH #define DUNE_LOCALFUNCTIONS_DUALMORTARBASIS_DUALP1_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 () {} /** \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 ! */ static constexpr GeometryType type () { return GeometryTypes::simplex(dim); } private: DualP1LocalBasis basis; DualP1LocalCoefficients coefficients; DualP1LocalInterpolation > interpolation; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/dualmortarbasis/dualp1/000077500000000000000000000000001411343327200260355ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/dualmortarbasis/dualp1/CMakeLists.txt000066400000000000000000000002651411343327200306000ustar00rootroot00000000000000install(FILES dualp1localbasis.hh dualp1localcoefficients.hh dualp1localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/dualmortarbasis/dualp1) dune-localfunctions-2.8.0/dune/localfunctions/dualmortarbasis/dualp1/dualp1localbasis.hh000066400000000000000000000075261411343327200316130ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/dualmortarbasis/dualp1/dualp1localcoefficients.hh000066400000000000000000000016341411343327200331450ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/dualmortarbasis/dualp1/dualp1localinterpolation.hh000066400000000000000000000027571411343327200334020ustar00rootroot00000000000000// -*- 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 #include namespace Dune { template class DualP1LocalInterpolation { public: //! \brief Local interpolation of a function template void interpolate (const F& ff, std::vector& out) const { typename LB::Traits::DomainType x; // If the dual functions are dual on the faces, // then adjust the interpolation weights const int faceDual(LB::faceDual); auto&& f = Impl::makeFunctionWithCallOperator(ff); // 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 DualP1::Traits::LocalBasisType::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.8.0/dune/localfunctions/dualmortarbasis/dualq1.hh000066400000000000000000000155331411343327200263660ustar00rootroot00000000000000// -*- 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 () { 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 ! */ static constexpr GeometryType type () { return GeometryTypes::cube(dim); } 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; }; 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(type(), 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::Impl::LagrangeCubeLocalBasis q1Basis; const auto& refElement = Dune::ReferenceElements::general(type()); // loop over faces for (int 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.8.0/dune/localfunctions/dualmortarbasis/dualq1/dualq1localcoefficients.hh000066400000000000000000000017221411343327200331450ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/dualmortarbasis/dualq1/dualq1localinterpolation.hh000066400000000000000000000037601411343327200333770ustar00rootroot00000000000000// -*- 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 #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& ff, std::vector& out) const { typename LB::Traits::DomainType x; auto&& f = Impl::makeFunctionWithCallOperator(ff); 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.8.0/dune/localfunctions/dualmortarbasis/test/000077500000000000000000000000001411343327200256265ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/dualmortarbasis/test/CMakeLists.txt000066400000000000000000000000571411343327200303700ustar00rootroot00000000000000dune_add_test(SOURCES test-biorthogonality.cc) dune-localfunctions-2.8.0/dune/localfunctions/dualmortarbasis/test/test-biorthogonality.cc000066400000000000000000000211761411343327200323360ustar00rootroot00000000000000// -*- 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; } dune-localfunctions-2.8.0/dune/localfunctions/hierarchical.hh000066400000000000000000000006331411343327200244140ustar00rootroot00000000000000// -*- 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 hierarchical LocalFiniteElements */ #include #include #include dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/000077500000000000000000000000001411343327200240715ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/CMakeLists.txt000066400000000000000000000004461411343327200266350ustar00rootroot00000000000000add_subdirectory(hierarchicalp2) add_subdirectory(hierarchicalp2withelementbubble) add_subdirectory(hierarchicalprismp2) install(FILES hierarchicalp2.hh hierarchicalp2withelementbubble.hh hierarchicalprismp2.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/hierarchical) dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/hierarchicalp2.hh000066400000000000000000000040761411343327200273010ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_HIERARCHICAL_P2_LOCALFINITEELEMENT_HH #define DUNE_HIERARCHICAL_P2_LOCALFINITEELEMENT_HH #include #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 () {} /** \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 ! */ static constexpr GeometryType type () { return GeometryTypes::simplex(dim); } private: HierarchicalSimplexP2LocalBasis basis; typename Traits::LocalCoefficientsType coefficients; HierarchicalSimplexP2LocalInterpolation > interpolation; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/hierarchicalp2/000077500000000000000000000000001411343327200267515ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/hierarchicalp2/CMakeLists.txt000066400000000000000000000002731411343327200315130ustar00rootroot00000000000000install(FILES hierarchicalsimplexp2localbasis.hh hierarchicalsimplexp2localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/hierarchical/hierarchicalp2) hierarchicalsimplexp2localbasis.hh000066400000000000000000000265241411343327200355430ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000055341411343327200373270ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #include namespace Dune { /** \tparam LB The LocalBasis implementation */ template class HierarchicalSimplexP2LocalInterpolation { public: template void interpolate (const F& ff, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; auto&& f = Impl::makeFunctionWithCallOperator(ff); 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; out[0] = f(x); x[0] = 1.0; out[2] = f(x); // Then: the edge dof x[0] = 0.5; y = f(x); 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; out[0] = f(x); x[0] = 1.0; x[1] = 0.0; out[2] = f(x); x[0] = 0.0; x[1] = 1.0; out[5] = f(x); // Then: the three edge dofs x[0] = 0.5; x[1] = 0.0; y = f(x); out[1] = y - 0.5*(out[0] + out[2]); x[0] = 0.0; x[1] = 0.5; y = f(x); out[3] = y - 0.5*(out[0] + out[5]); x[0] = 0.5; x[1] = 0.5; y = f(x); 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; out[0] = f(x); x[0] = 1.0; x[1] = 0.0; x[2] = 0.0; out[2] = f(x); x[0] = 0.0; x[1] = 1.0; x[2] = 0.0; out[5] = f(x); x[0] = 0.0; x[1] = 0.0; x[2] = 1.0; out[9] = f(x); // Then: the six edge dofs x[0] = 0.5; x[1] = 0.0; x[2] = 0.0; y = f(x); out[1] = y - 0.5*(out[0] + out[2]); x[0] = 0.0; x[1] = 0.5; x[2] = 0.0; y = f(x); out[3] = y - 0.5*(out[0] + out[5]); x[0] = 0.5; x[1] = 0.5; x[2] = 0.0; y = f(x); out[4] = y - 0.5*(out[2] + out[5]); x[0] = 0.0; x[1] = 0.0; x[2] = 0.5; y = f(x); out[6] = y - 0.5*(out[0] + out[9]); x[0] = 0.5; x[1] = 0.0; x[2] = 0.5; y = f(x); out[7] = y - 0.5*(out[2] + out[9]); x[0] = 0.0; x[1] = 0.5; x[2] = 0.5; y = f(x); out[8] = y - 0.5*(out[5] + out[9]); break; } } }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/hierarchicalp2withelementbubble.hh000066400000000000000000000042421411343327200327160ustar00rootroot00000000000000// -*- 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 () {} /** \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 ! */ static constexpr GeometryType type () { return GeometryTypes::triangle; } private: HierarchicalSimplexP2WithElementBubbleLocalBasis basis_; HierarchicalSimplexP2WithElementBubbleLocalCoefficients coefficients_; HierarchicalSimplexP2WithElementBubbleLocalInterpolation > interpolation_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/hierarchicalp2withelementbubble/000077500000000000000000000000001411343327200323735ustar00rootroot00000000000000CMakeLists.txt000066400000000000000000000002461411343327200350560ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/hierarchicalp2withelementbubbleinstall(FILES hierarchicalsimplexp2withelementbubble.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/hierarchical/hierarchicalp2withelementbubble) hierarchicalsimplexp2withelementbubble.hh000066400000000000000000000366371411343327200425600ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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& ff, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; out.resize(7); auto&& f = Impl::makeFunctionWithCallOperator(ff); // vertices x[0] = 0.0; x[1] = 0.0; out[0] = f(x); x[0] = 1.0; x[1] = 0.0; out[2] = f(x); x[0] = 0.0; x[1] = 1.0; out[5] = f(x); // edge bubbles x[0] = 0.5; x[1] = 0.0; y = f(x); out[1] = y - out[0]*(1-x[0]) - out[2]*x[0]; x[0] = 0.0; x[1] = 0.5; y = f(x); out[3] = y - out[0]*(1-x[1]) - out[5]*x[1]; x[0] = 0.5; x[1] = 0.5; y = f(x); out[4] = y - out[2]*x[0] - out[5]*x[1]; // element bubble x[0] = 1.0/3; x[1] = 1.0/3; y = f(x); /** \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.8.0/dune/localfunctions/hierarchical/hierarchicalprismp2.hh000066400000000000000000000037251411343327200303540ustar00rootroot00000000000000// -*- 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, Impl::LagrangePrismLocalCoefficients<2>, HierarchicalPrismP2LocalInterpolation > > Traits; /** \todo Please doc me ! */ HierarchicalPrismP2LocalFiniteElement () {} /** \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 ! */ static constexpr GeometryType type () { return GeometryTypes::prism; } private: HierarchicalPrismP2LocalBasis basis; /** \todo Stupid, Pk local coefficients can't be parametrized */ Impl::LagrangePrismLocalCoefficients<2> coefficients; HierarchicalPrismP2LocalInterpolation > interpolation; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/hierarchicalprismp2/000077500000000000000000000000001411343327200300245ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/hierarchical/hierarchicalprismp2/CMakeLists.txt000066400000000000000000000002741411343327200325670ustar00rootroot00000000000000install(FILES hierarchicalprismp2localbasis.hh hierarchicalprismp2localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/hierarchical/hierarchicalprismp2) hierarchicalprismp2localbasis.hh000066400000000000000000000204161411343327200362610ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000050231411343327200400440ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #include namespace Dune { /** \tparam LB The LocalBasis implementation */ template class HierarchicalPrismP2LocalInterpolation { public: template void interpolate (const F& ff, std::vector& out) const { typename LB::Traits::DomainType x; typename LB::Traits::RangeType y; out.resize(18); auto&& f = Impl::makeFunctionWithCallOperator(ff); //First the vertex dofs x[0] = 0.0; x[1] = 0.0; x[2] = 0.0; out[0] = f(x); x[0] = 1.0; x[1] = 0.0; x[2] = 0.0; out[1] = f(x); x[0] = 0.0; x[1] = 1.0; x[2] = 0.0; out[2] = f(x); x[0] = 0.0; x[1] = 0.0; x[2] = 1.0; out[3] = f(x); x[0] = 1.0; x[1] = 0.0; x[2] = 1.0; out[4] = f(x); x[0] = 0.0; x[1] = 1.0; x[2] = 1.0; out[5] = f(x); // Then: the 9 edge dofs and the 3 face dofs x[0] = 0.0; x[1] = 0.0; x[2] = 0.5; y = f(x); out[6] = y - 0.5*(out[0] + out[3]); x[0] = 1.0; x[1] = 0.0; x[2] = 0.5; y = f(x); out[7] = y - 0.5*(out[1] + out[4]); x[0] = 0.0; x[1] = 1.0; x[2] = 0.5; y = f(x); out[8] = y - 0.5*(out[2] + out[5]); x[0] = 0.5; x[1] = 0.0; x[2] = 0.0; y = f(x); out[9] = y - 0.5*(out[0] + out[1]); x[0] = 0.0; x[1] = 0.5; x[2] = 0.0; y = f(x); out[10] = y - 0.5*(out[2] + out[0]); x[0] = 0.5; x[1] = 0.5; x[2] = 0.0; y = f(x); out[11] = y - 0.5*(out[2] + out[1]); x[0] = 0.5; x[1] = 0.0; x[2] = 1.0; y = f(x); out[12] = y - 0.5*(out[3] + out[4]); x[0] = 0.0; x[1] = 0.5; x[2] = 1.0; y = f(x); out[13] = y - 0.5*(out[3] + out[5]); x[0] = 0.5; x[1] = 0.5; x[2] = 1.0; y = f(x); out[14] = y - 0.5*(out[4] + out[5]); //faces x[0] = 0.5; x[1] = 0.0; x[2] = 0.5; y = f(x); 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; y = f(x); 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; y = f(x); out[17] = y - 0.25*(out[2] + out[1] + out[4] + out[5] ); } }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange.hh000066400000000000000000000072641411343327200235650ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_HH #define DUNE_LOCALFUNCTIONS_LAGRANGE_HH /** \file * \brief Convenience header that includes all implementations of Lagrange finite elements */ // Headers for Lagrange elements with run-time order #include #include #include #include #include // Headers for Lagrange elements with compile-time order #include #include #include #include #include #include #include #include #include #include #include #include #include #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: * - EquidistantPointSet: 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_LOCALFUNCTIONS_LAGRANGE_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/000077500000000000000000000000001411343327200232335ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/lagrange/CMakeLists.txt000066400000000000000000000007541411343327200260010ustar00rootroot00000000000000add_subdirectory(p0) install(FILES emptypoints.hh equidistantpoints.hh interpolation.hh lagrangebasis.hh lagrangecoefficients.hh lagrangecube.hh lagrangelfecache.hh lagrangeprism.hh lagrangepyramid.hh lagrangesimplex.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.8.0/dune/localfunctions/lagrange/emptypoints.hh000066400000000000000000000037141411343327200261540ustar00rootroot00000000000000// -*- 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_; } const Field weight () const { return weight_; } Vector point_; LocalKey localKey_; Field weight_; }; // 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 std::size_t 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(); } std::size_t order () const { return order_; } std::size_t size () const { return points_.size(); } protected: std::size_t order_; std::vector< LagrangePoint > points_; }; } #endif // DUNE_LAGRANGE_EMPTYPOINTS_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/equidistantpoints.hh000066400000000000000000000152331411343327200273470ustar00rootroot00000000000000#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 ( const GeometryType& gt, std::size_t order ) { const int dim = gt.dim(); if( dim > 0 ) { const GeometryType baseGeometryType = Impl::getBase( gt ); if( gt.isConical() ) { std::size_t size = 0; for( unsigned int o = 0; o <= order; ++o ) size += numLagrangePoints( baseGeometryType, o ); return size; } else return numLagrangePoints( baseGeometryType, order ) * (order+1); } else return 1; } [[deprecated("Use numLagrangePoints(const GeometryType& gt, std::size_t order ) instead.")]] inline std::size_t numLagrangePoints ( unsigned int topologyId, unsigned int dim, std::size_t order ) { return numLagrangePoints ( GeometryType(topologyId, dim), order); } // equidistantLagrangePoints // ------------------------- template< class ct, unsigned int cdim > inline static unsigned int equidistantLagrangePoints ( const GeometryType& gt, unsigned int codim, std::size_t order, unsigned int *count, LagrangePoint< ct, cdim > *points ) { const unsigned int dim = gt.dim(); assert( (0 <= codim) && (codim <= dim) && (dim <= cdim) ); if( dim > 0 ) { const GeometryType baseGeometryType = Impl::getBase( gt ); const unsigned int numBaseN = (codim < dim ? Geo::Impl::size( baseGeometryType.id(), baseGeometryType.dim(), codim ) : 0); const unsigned int numBaseM = (codim > 0 ? Geo::Impl::size( baseGeometryType.id(), baseGeometryType.dim(), codim-1 ) : 0); if( gt.isPrismatic() ) { unsigned int size = 0; if( codim < dim ) { for( unsigned int i = 1; i < order; ++i ) { const unsigned int n = equidistantLagrangePoints( baseGeometryType, 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( baseGeometryType, 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( baseGeometryType, 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( baseGeometryType, 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; } } template< class ct, unsigned int cdim > [[deprecated("Use equidistantLagrangePoints ( GeometryType gt, ... ) instead.")]] inline static unsigned int equidistantLagrangePoints ( unsigned int topologyId, unsigned int dim, unsigned int codim, std::size_t order, unsigned int *count, LagrangePoint< ct, cdim > *points ) { return equidistantLagrangePoints ( GeometryType(topologyId, dim), codim, order, *count, *points ); } // 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 ( std::size_t order ) : Base( order ) {} void build ( GeometryType gt ) { assert( gt.dim() == dimension ); points_.resize( numLagrangePoints( gt, order() ) ); typename Base::LagrangePoint *p = points_.data(); std::vector< unsigned int > count; for( unsigned int mydim = 0; mydim <= dimension; ++mydim ) { count.resize( Geo::Impl::size( gt.id(), dimension, dimension-mydim ) ); std::fill( count.begin(), count.end(), 0u ); p += equidistantLagrangePoints( gt, dimension-mydim, order(), count.data(), p ); } const auto &refElement = referenceElement(gt); F weight = refElement.volume()/F(double(points_.size())); for (auto &p : points_) p.weight_ = weight; } template< GeometryType::Id geometryId > bool build () { build( GeometryType( geometryId ) ); return true; } bool buildCube () { return build< GeometryTypes::cube(dim) > (); } static bool supports ( GeometryType gt, std::size_t order ) { return true; } template< GeometryType::Id geometryId> static bool supports ( std::size_t order ) { return supports( GeometryType( geometryId ), order ); } private: using Base::points_; }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_EQUIDISTANTPOINTS_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/interpolation.hh000066400000000000000000000102421411343327200264420ustar00rootroot00000000000000// -*- 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 #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_; } template< class Fn, class Vector > auto interpolate ( const Fn &fn, Vector &coefficients, PriorityTag< 1 > ) const -> std::enable_if_t< std::is_invocable_v< const Fn &, decltype( this->lagrangePoints_.begin()->point() ) > > { unsigned int index = 0; for( const auto &lp : lagrangePoints_ ) field_cast( fn( lp.point() ), coefficients[ index++ ] ); } template< class Fn, class Vector > auto interpolate ( const Fn &fn, Vector &coefficients, PriorityTag< 0 > ) const -> std::enable_if_t< models, Fn>(), void> { unsigned int index = 0; for( const auto &lp : lagrangePoints_ ) { typename Fn::RangeType val; fn.evaluate( field_cast< typename Fn::DomainType::field_type >( lp.point() ), val ); field_cast( val, coefficients[ index++ ] ); } } public: template< class Fn, class Vector > auto interpolate ( const Fn &fn, Vector &coefficients ) const -> std::enable_if_t< std::is_same< decltype(std::declval().resize(1) ),void >::value,void> { coefficients.resize( lagrangePoints_.size() ); interpolate( fn, coefficients, PriorityTag< 42 >() ); } template< class Basis, class Matrix > auto interpolate ( const Basis &basis, Matrix &coefficients ) const -> std::enable_if_t< std::is_same< decltype(std::declval().rowPtr(0)), typename Matrix::Field* >::value,void> { coefficients.resize( lagrangePoints_.size(), basis.size( ) ); unsigned int index = 0; for( const auto &lp : lagrangePoints_ ) basis.template evaluate< 0 >( lp.point(), coefficients.rowPtr( index++ ) ); } const LagrangePointSet &lagrangePoints () const { return lagrangePoints_; } }; // LocalLagrangeInterpolationFactory // --------------------------------- template< template class LP, unsigned int dim, class F > struct LagrangeInterpolationFactory { typedef LagrangeCoefficientsFactory LagrangePointSetFactory; typedef typename LagrangePointSetFactory::Object LagrangePointSet; typedef typename LagrangePointSetFactory::Key Key; typedef const LocalLagrangeInterpolation< LP,dim,F > Object; template< GeometryType::Id geometryId > static Object *create ( const Key &key ) { const LagrangePointSet *lagrangeCoeff = LagrangePointSetFactory::template create< geometryId >( key ); if ( lagrangeCoeff == 0 ) return 0; else return new Object( *lagrangeCoeff ); } template< GeometryType::Id geometryId > static bool supports ( const Key &key ) { return true; } static void release( Object *object) { LagrangePointSetFactory::release( object->points() ); delete object; } }; } #endif // #ifndef DUNE_LAGRANGEBASIS_INTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/lagrangebasis.hh000066400000000000000000000013261411343327200263600ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/lagrange/lagrangecoefficients.hh000066400000000000000000000022611411343327200277170ustar00rootroot00000000000000// -*- 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 namespace Dune { template< template class LP, unsigned int dim, class F> struct LagrangeCoefficientsFactory { static const unsigned int dimension = dim; const typedef LP Object; typedef std::size_t Key; template< GeometryType::Id geometryId > static Object *create ( 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; } static void release( Object *object ) { delete object; } }; } #endif // DUNE_LAGRANGECOEFFICIENTS_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/lagrangecube.hh000066400000000000000000000554741411343327200262120ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGECUBE_HH #define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGECUBE_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Impl { // Forward declaration template class LagrangeCubeLocalInterpolation; /** \brief Lagrange shape functions of arbitrary order on the reference cube [0,1]^d 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 dim Dimension of the domain cube \tparam k Polynomial order */ template class LagrangeCubeLocalBasis { friend class LagrangeCubeLocalInterpolation >; // i-th Lagrange polynomial of degree k in one dimension static R p(unsigned int i, D x) { R result(1.0); for (unsigned int j=0; j<=k; j++) if (j!=i) result *= (k*x-j)/((int)i-(int)j); return result; } // derivative of ith Lagrange polynomial of degree k in one dimension static R dp(unsigned int i, D x) { R result(0.0); for (unsigned int j=0; j<=k; j++) { if (j!=i) { R prod( (k*1.0)/((int)i-(int)j) ); for (unsigned int l=0; l<=k; l++) if (l!=i && l!=j) prod *= (k*x-l)/((int)i-(int)l); result += prod; } } return result; } // Second derivative of j-th Lagrange polynomial of degree k in one dimension // Formula and notation taken from https://en.wikipedia.org/wiki/Lagrange_polynomial#Derivatives static R ddp(unsigned int j, D x) { R result(0.0); for (unsigned int i=0; i<=k; i++) { if (i==j) continue; R sum(0); for (unsigned int m=0; m<=k; m++) { if (m==i || m==j) continue; R prod( (k*1.0)/((int)j-(int)m) ); for (unsigned int l=0; l<=k; l++) if (l!=i && l!=j && l!=m) prod *= (k*x-l)/((int)j-(int)l); sum += prod; } result += sum * ( (k*1.0)/((int)j-(int)i) ); } return result; } // Return i as a d-digit number in the (k+1)-nary system static std::array multiindex (unsigned int i) { std::array alpha; for (unsigned int j=0; j,R,1,FieldVector,FieldMatrix >; /** \brief Number of shape functions */ static constexpr unsigned int size () { return power(k+1, dim); } //! \brief Evaluate all shape functions void evaluateFunction(const typename Traits::DomainType& x, std::vector& out) const { out.resize(size()); // Specialization for zero-order case if (k==0) { out[0] = 1; return; } if (k==1) { for (size_t i=0; i alpha(multiindex(i)); // initialize product out[i] = 1.0; // dimension by dimension for (unsigned int j=0; j& out) const { out.resize(size()); // Specialization for k==0 if (k==0) { std::fill(out[0][0].begin(), out[0][0].end(), 0); return; } // Specialization for k==1 if (k==1) { // Loop over all shape functions for (size_t i=0; i alpha(multiindex(i)); // Loop over all coordinate directions for (unsigned int j=0; j& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); out.resize(size()); if (k==0) { out[0] = (totalOrder==0); return; } if (k==1) { 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, otherwise to -1 out[i] = (i & (1< 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; l1 // 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 class LagrangeCubeLocalCoefficients { // Return i as a d-digit number in the (k+1)-nary system static std::array multiindex (unsigned int i) { std::array alpha; for (unsigned int j=0; j& subEntity) { assert(k>0); unsigned lastIndex=0; /* edge and vertex numbering 0----0----1 */ // edge (0) subEntity[lastIndex++] = 0; // corner 0 for (unsigned i = 0; i < k - 1; ++i) subEntity[lastIndex++] = 0; // inner dofs of element (0) subEntity[lastIndex++] = 1; // corner 1 assert(power(k+1,dim)==lastIndex); } void setup2d(std::vector& subEntity) { assert(k>0); 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 < k - 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 < k - 1; ++e) { subEntity[lastIndex++] = 0; // left edge (0) for (unsigned i = 0; i < k - 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 < k - 1; ++i) subEntity[lastIndex++] = 3; // inner dofs of upper edge (3) subEntity[lastIndex++] = 3; // corner 3 assert(power(k+1,dim)==lastIndex); } void setup3d(std::vector& subEntity) { assert(k>0); unsigned lastIndex=0; #ifndef NDEBUG const unsigned numIndices = power(k+1,dim); const unsigned numFaceIndices = power(k+1,dim-1); #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 < k - 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 < k - 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 < k - 1; ++e) { subEntity[lastIndex++] = 8; // left edge (8) for (unsigned i = 0; i < k - 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 < k - 1; ++i) subEntity[lastIndex++] = 11; // inner dofs of upper edge (11) subEntity[lastIndex++] = 7; // corner 7 assert(numIndices==lastIndex); } public: //! \brief Default constructor LagrangeCubeLocalCoefficients () : localKeys_(size()) { if (k==0) { localKeys_[0] = LocalKey(0,0,0); return; } if (k==1) { for (std::size_t i=0; i codim(size()); for (std::size_t i=0; i mIdx = multiindex(i); for (unsigned int j=0; j index(size()); for (std::size_t i=0; i mIdx = multiindex(i); for (int j=dim-1; j>=0; j--) if (mIdx[j]>0 && mIdx[j] subEntity(size()); if (dim==1) { setup1d(subEntity); } else if (dim==2) { setup2d(subEntity); } else if (dim==3) { setup3d(subEntity); } else DUNE_THROW(Dune::NotImplemented, "LagrangeCubeLocalCoefficients for order " << k << " and dim == " << dim); for (size_t i=0; i localKeys_; }; /** \brief Evaluate the degrees of freedom of a Lagrange basis * * \tparam LocalBasis The corresponding set of shape functions */ template class LagrangeCubeLocalInterpolation { public: /** \brief Evaluate a given function at the Lagrange nodes * * \tparam F Type of function to evaluate * \tparam C Type used for the values of the function * \param[in] ff Function to evaluate * \param[out] out Array of function values */ template void interpolate (const F& ff, std::vector& out) const { constexpr auto dim = LocalBasis::Traits::dimDomain; constexpr auto k = LocalBasis::order(); using D = typename LocalBasis::Traits::DomainFieldType; typename LocalBasis::Traits::DomainType x; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(LocalBasis::size()); // Specialization for zero-order case if (k==0) { auto center = ReferenceElements::cube().position(0,0); out[0] = f(center); return; } // Specialization for first-order case if (k==1) { for (unsigned int i=0; i alpha(LocalBasis::multiindex(i)); // Generate coordinate of the i-th Lagrange point for (unsigned int j=0; j class LagrangeCubeLocalFiniteElement { public: /** \brief Export number types, dimensions, etc. */ using Traits = LocalFiniteElementTraits, Impl::LagrangeCubeLocalCoefficients, Impl::LagrangeCubeLocalInterpolation > >; /** \brief Default constructor * * \deprecated This explicit implementation only exists to work around a bug in clang 3.8 * which disappeared in clang 6 */ LagrangeCubeLocalFiniteElement() {} /** \brief Returns the local basis, i.e., the set of shape functions */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \brief Returns the assignment of the degrees of freedom to the element subentities */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \brief Returns object that evaluates degrees of freedom */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief The number of shape functions */ static constexpr std::size_t size () { return power(k+1,dim); } /** \brief The reference element that the local finite element is defined on */ static constexpr GeometryType type () { return GeometryTypes::cube(dim); } private: Impl::LagrangeCubeLocalBasis basis_; Impl::LagrangeCubeLocalCoefficients coefficients_; Impl::LagrangeCubeLocalInterpolation > interpolation_; }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGECUBE_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/lagrangelfecache.hh000066400000000000000000000116621411343327200270150ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGELFECACHE_HH #define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGELFECACHE_HH #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Impl { // Provide implemented Lagrange local finite elements template struct ImplementedLagrangeFiniteElements : public FixedDimLocalGeometryTypeIndex { using FixedDimLocalGeometryTypeIndex::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::simplex(dim)), []() { return PkLocalFiniteElement(); }), std::make_pair(index(GeometryTypes::cube(dim)), []() { return QkLocalFiniteElement(); }) ); } }; template struct ImplementedLagrangeFiniteElements : public FixedDimLocalGeometryTypeIndex { using FixedDimLocalGeometryTypeIndex::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::simplex(dim)), []() { return P0LocalFiniteElement(GeometryTypes::simplex(dim)); }), std::make_pair(index(GeometryTypes::cube(dim)), []() { return P0LocalFiniteElement(GeometryTypes::cube(dim)); }), std::make_pair(index(GeometryTypes::none(dim)), []() { return P0LocalFiniteElement(GeometryTypes::none(dim)); }) ); } }; template struct ImplementedLagrangeFiniteElements : public FixedDimLocalGeometryTypeIndex<3> { using FixedDimLocalGeometryTypeIndex<3>::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::tetrahedron), []() { return P0LocalFiniteElement(GeometryTypes::tetrahedron); }), std::make_pair(index(GeometryTypes::hexahedron), []() { return P0LocalFiniteElement(GeometryTypes::hexahedron); }), std::make_pair(index(GeometryTypes::prism), []() { return P0LocalFiniteElement(GeometryTypes::prism); }), std::make_pair(index(GeometryTypes::pyramid), []() { return P0LocalFiniteElement(GeometryTypes::pyramid); }) ); } }; template struct ImplementedLagrangeFiniteElements : public FixedDimLocalGeometryTypeIndex<3> { using FixedDimLocalGeometryTypeIndex<3>::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::tetrahedron), []() { return PkLocalFiniteElement(); }), std::make_pair(index(GeometryTypes::hexahedron), []() { return QkLocalFiniteElement(); }), std::make_pair(index(GeometryTypes::prism), []() { return PrismP1LocalFiniteElement(); }), std::make_pair(index(GeometryTypes::pyramid), []() { return PyramidP1LocalFiniteElement(); }) ); } }; template struct ImplementedLagrangeFiniteElements : public FixedDimLocalGeometryTypeIndex<3> { using FixedDimLocalGeometryTypeIndex<3>::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::tetrahedron), []() { return PkLocalFiniteElement(); }), std::make_pair(index(GeometryTypes::hexahedron), []() { return QkLocalFiniteElement(); }), std::make_pair(index(GeometryTypes::prism), []() { return PrismP2LocalFiniteElement(); }), std::make_pair(index(GeometryTypes::pyramid), []() { return PyramidP2LocalFiniteElement(); }) ); } }; } // namespace Impl /** \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. * * \tparam D Type used for domain coordinates * \tparam R Type used for shape function values * \tparam dim Element dimension * \tparam order Element order * * The cached finite element implementations can be obtained using get(GeometryType). */ template using LagrangeLocalFiniteElementCache = LocalFiniteElementVariantCache>; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGELFECACHE_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/lagrangeprism.hh000066400000000000000000000663231411343327200264210ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPRISM_HH #define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPRISM_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Impl { /** \brief Lagrange shape functions of arbitrary order on the three-dimensional reference prism 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 */ template class LagrangePrismLocalBasis { static constexpr std::size_t dim = 3; public: using Traits = LocalBasisTraits,R,1,FieldVector,FieldMatrix >; /** \brief Number of shape functions */ static constexpr unsigned int size () { return binomial(k+2,2u) * (k+1); } //! \brief Evaluate all shape functions void evaluateFunction(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); // Specialization for zero-order case if (k==0) { out[0] = 1; return; } if (k==1) { 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]; return; } if (k==2) { FieldVector segmentShapeFunction; segmentShapeFunction[0] = 1 + in[2] * (-3 + 2*in[2]); segmentShapeFunction[1] = in[2] * (4 - 4*in[2]); segmentShapeFunction[2] = in[2] * (-1 + 2*in[2]); FieldVector triangleShapeFunction; triangleShapeFunction[0] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]); triangleShapeFunction[1] = 2 * in[0] * (-0.5 + in[0]); triangleShapeFunction[2] = 2 * in[1] * (-0.5 + in[1]); triangleShapeFunction[3] = 4*in[0] * (1 - in[0] - in[1]); triangleShapeFunction[4] = 4*in[1] * (1 - in[0] - in[1]); triangleShapeFunction[5] = 4*in[0]*in[1]; // lower triangle: out[0] = triangleShapeFunction[0] * segmentShapeFunction[0]; out[1] = triangleShapeFunction[1] * segmentShapeFunction[0]; out[2] = triangleShapeFunction[2] * segmentShapeFunction[0]; //upper triangle out[3] = triangleShapeFunction[0] * segmentShapeFunction[2]; out[4] = triangleShapeFunction[1] * segmentShapeFunction[2]; out[5] = triangleShapeFunction[2] * segmentShapeFunction[2]; // vertical edges out[6] = triangleShapeFunction[0] * segmentShapeFunction[1]; out[7] = triangleShapeFunction[1] * segmentShapeFunction[1]; out[8] = triangleShapeFunction[2] * segmentShapeFunction[1]; // lower triangle edges out[9] = triangleShapeFunction[3] * segmentShapeFunction[0]; out[10] = triangleShapeFunction[4] * segmentShapeFunction[0]; out[11] = triangleShapeFunction[5] * segmentShapeFunction[0]; // upper triangle edges out[12] = triangleShapeFunction[3] * segmentShapeFunction[2]; out[13] = triangleShapeFunction[4] * segmentShapeFunction[2]; out[14] = triangleShapeFunction[5] * segmentShapeFunction[2]; // quadrilateral sides out[15] = triangleShapeFunction[3] * segmentShapeFunction[1]; out[16] = triangleShapeFunction[4] * segmentShapeFunction[1]; out[17] = triangleShapeFunction[5] * segmentShapeFunction[1]; return; } DUNE_THROW(NotImplemented, "LagrangePrismLocalBasis::evaluateFunction for order " << k); } /** \brief Evaluate Jacobian of all shape functions * * \param x Point in the reference prism where to evaluation the Jacobians * \param[out] out The Jacobians of all shape functions at the point x */ void evaluateJacobian(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); // Specialization for k==0 if (k==0) { std::fill(out[0][0].begin(), out[0][0].end(), 0); return; } if (k==1) { out[0][0] = {in[2]-1, in[2]-1, in[0]+in[1]-1}; out[1][0] = {1-in[2], 0, -in[0]}; out[2][0] = { 0, 1-in[2], -in[1]}; out[3][0] = { -in[2], -in[2], 1-in[0]-in[1]}; out[4][0] = { in[2], 0, in[0]}; out[5][0] = { 0, in[2], in[1]}; return; } if (k==2) { // Second-order shape functions on a triangle, and the first derivatives FieldVector triangleShapeFunction; triangleShapeFunction[0] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]); triangleShapeFunction[1] = 2 * in[0] * (-0.5 + in[0]); triangleShapeFunction[2] = 2 * in[1] * (-0.5 + in[1]); triangleShapeFunction[3] = 4*in[0] * (1 - in[0] - in[1]); triangleShapeFunction[4] = 4*in[1] * (1 - in[0] - in[1]); triangleShapeFunction[5] = 4*in[0]*in[1]; std::array,6> triangleShapeFunctionDer; triangleShapeFunctionDer[0] = {-3 + 4*(in[0] + in[1]), -3 + 4*(in[0] + in[1])}; triangleShapeFunctionDer[1] = { -1 + 4*in[0], 0}; triangleShapeFunctionDer[2] = { 0, -1 + 4*in[1]}; triangleShapeFunctionDer[3] = { 4 - 8*in[0] - 4*in[1], -4*in[0]}; triangleShapeFunctionDer[4] = { -4*in[1], 4 - 4*in[0] - 8*in[1]}; triangleShapeFunctionDer[5] = { 4*in[1], 4*in[0]}; // Second-order shape functions on a line, and the first derivatives FieldVector segmentShapeFunction; segmentShapeFunction[0] = 1 + in[2] * (-3 + 2*in[2]); segmentShapeFunction[1] = in[2] * ( 4 - 4*in[2]); segmentShapeFunction[2] = in[2] * (-1 + 2*in[2]); FieldVector segmentShapeFunctionDer; segmentShapeFunctionDer[0] = -3 + 4*in[2]; segmentShapeFunctionDer[1] = 4 - 8*in[2]; segmentShapeFunctionDer[2] = -1 + 4*in[2]; // lower triangle: out[0][0][0] = triangleShapeFunctionDer[0][0] * segmentShapeFunction[0]; out[0][0][1] = triangleShapeFunctionDer[0][1] * segmentShapeFunction[0]; out[0][0][2] = triangleShapeFunction[0] * segmentShapeFunctionDer[0]; out[1][0][0] = triangleShapeFunctionDer[1][0] * segmentShapeFunction[0]; out[1][0][1] = triangleShapeFunctionDer[1][1] * segmentShapeFunction[0]; out[1][0][2] = triangleShapeFunction[1] * segmentShapeFunctionDer[0]; out[2][0][0] = triangleShapeFunctionDer[2][0] * segmentShapeFunction[0]; out[2][0][1] = triangleShapeFunctionDer[2][1] * segmentShapeFunction[0]; out[2][0][2] = triangleShapeFunction[2] * segmentShapeFunctionDer[0]; //upper triangle out[3][0][0] = triangleShapeFunctionDer[0][0] * segmentShapeFunction[2]; out[3][0][1] = triangleShapeFunctionDer[0][1] * segmentShapeFunction[2]; out[3][0][2] = triangleShapeFunction[0] * segmentShapeFunctionDer[2]; out[4][0][0] = triangleShapeFunctionDer[1][0] * segmentShapeFunction[2]; out[4][0][1] = triangleShapeFunctionDer[1][1] * segmentShapeFunction[2]; out[4][0][2] = triangleShapeFunction[1] * segmentShapeFunctionDer[2]; out[5][0][0] = triangleShapeFunctionDer[2][0] * segmentShapeFunction[2]; out[5][0][1] = triangleShapeFunctionDer[2][1] * segmentShapeFunction[2]; out[5][0][2] = triangleShapeFunction[2] * segmentShapeFunctionDer[2]; // vertical edges out[6][0][0] = triangleShapeFunctionDer[0][0] * segmentShapeFunction[1]; out[6][0][1] = triangleShapeFunctionDer[0][1] * segmentShapeFunction[1]; out[6][0][2] = triangleShapeFunction[0] * segmentShapeFunctionDer[1]; out[7][0][0] = triangleShapeFunctionDer[1][0] * segmentShapeFunction[1]; out[7][0][1] = triangleShapeFunctionDer[1][1] * segmentShapeFunction[1]; out[7][0][2] = triangleShapeFunction[1] * segmentShapeFunctionDer[1]; out[8][0][0] = triangleShapeFunctionDer[2][0] * segmentShapeFunction[1]; out[8][0][1] = triangleShapeFunctionDer[2][1] * segmentShapeFunction[1]; out[8][0][2] = triangleShapeFunction[2] * segmentShapeFunctionDer[1]; // lower triangle edges out[9][0][0] = triangleShapeFunctionDer[3][0] * segmentShapeFunction[0]; out[9][0][1] = triangleShapeFunctionDer[3][1] * segmentShapeFunction[0]; out[9][0][2] = triangleShapeFunction[3] * segmentShapeFunctionDer[0]; out[10][0][0] = triangleShapeFunctionDer[4][0] * segmentShapeFunction[0]; out[10][0][1] = triangleShapeFunctionDer[4][1] * segmentShapeFunction[0]; out[10][0][2] = triangleShapeFunction[4] * segmentShapeFunctionDer[0]; out[11][0][0] = triangleShapeFunctionDer[5][0] * segmentShapeFunction[0]; out[11][0][1] = triangleShapeFunctionDer[5][1] * segmentShapeFunction[0]; out[11][0][2] = triangleShapeFunction[5] * segmentShapeFunctionDer[0]; // upper triangle edges out[12][0][0] = triangleShapeFunctionDer[3][0] * segmentShapeFunction[2]; out[12][0][1] = triangleShapeFunctionDer[3][1] * segmentShapeFunction[2]; out[12][0][2] = triangleShapeFunction[3] * segmentShapeFunctionDer[2]; out[13][0][0] = triangleShapeFunctionDer[4][0] * segmentShapeFunction[2]; out[13][0][1] = triangleShapeFunctionDer[4][1] * segmentShapeFunction[2]; out[13][0][2] = triangleShapeFunction[4] * segmentShapeFunctionDer[2]; out[14][0][0] = triangleShapeFunctionDer[5][0] * segmentShapeFunction[2]; out[14][0][1] = triangleShapeFunctionDer[5][1] * segmentShapeFunction[2]; out[14][0][2] = triangleShapeFunction[5] * segmentShapeFunctionDer[2]; // quadrilateral sides out[15][0][0] = triangleShapeFunctionDer[3][0] * segmentShapeFunction[1]; out[15][0][1] = triangleShapeFunctionDer[3][1] * segmentShapeFunction[1]; out[15][0][2] = triangleShapeFunction[3] * segmentShapeFunctionDer[1]; out[16][0][0] = triangleShapeFunctionDer[4][0] * segmentShapeFunction[1]; out[16][0][1] = triangleShapeFunctionDer[4][1] * segmentShapeFunction[1]; out[16][0][2] = triangleShapeFunction[4] * segmentShapeFunctionDer[1]; out[17][0][0] = triangleShapeFunctionDer[5][0] * segmentShapeFunction[1]; out[17][0][1] = triangleShapeFunctionDer[5][1] * segmentShapeFunction[1]; out[17][0][2] = triangleShapeFunction[5] * segmentShapeFunctionDer[1]; return; } DUNE_THROW(NotImplemented, "LagrangePrismLocalBasis::evaluateJacobian for order " << k); } /** \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 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); out.resize(size()); if (totalOrder == 0) { evaluateFunction(in, out); return; } // Specialization for zero-order finite elements if (k==0) { out[0] = 0; return; } // Specialization for first-order finite elements if (k==1) { if (totalOrder == 1) { auto 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; 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()); std::fill(out.begin(), out.end(), 0.0); } return; } // Specialization for second-order finite elements if (k==2) { if (totalOrder == 1) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); switch (direction) { case 0: { FieldVector triangleShapeFunctionDerX; triangleShapeFunctionDerX[0] = -3 + 4*(in[0] + in[1]); triangleShapeFunctionDerX[1] = -1 + 4* in[0]; triangleShapeFunctionDerX[2] = 0; triangleShapeFunctionDerX[3] = 4 - 8* in[0] - 4*in[1]; triangleShapeFunctionDerX[4] = -4*in[1]; triangleShapeFunctionDerX[5] = 4*in[1]; FieldVector segmentShapeFunction; segmentShapeFunction[0] = 1 + in[2] * (-3 + 2*in[2]); segmentShapeFunction[1] = in[2] * ( 4 - 4*in[2]); segmentShapeFunction[2] = in[2] * (-1 + 2*in[2]); out[0] = triangleShapeFunctionDerX[0] * segmentShapeFunction[0]; out[1] = triangleShapeFunctionDerX[1] * segmentShapeFunction[0]; out[2] = triangleShapeFunctionDerX[2] * segmentShapeFunction[0]; out[3] = triangleShapeFunctionDerX[0] * segmentShapeFunction[2]; out[4] = triangleShapeFunctionDerX[1] * segmentShapeFunction[2]; out[5] = triangleShapeFunctionDerX[2] * segmentShapeFunction[2]; out[6] = triangleShapeFunctionDerX[0] * segmentShapeFunction[1]; out[7] = triangleShapeFunctionDerX[1] * segmentShapeFunction[1]; out[8] = triangleShapeFunctionDerX[2] * segmentShapeFunction[1]; out[9] = triangleShapeFunctionDerX[3] * segmentShapeFunction[0]; out[10] = triangleShapeFunctionDerX[4] * segmentShapeFunction[0]; out[11] = triangleShapeFunctionDerX[5] * segmentShapeFunction[0]; out[12] = triangleShapeFunctionDerX[3] * segmentShapeFunction[2]; out[13] = triangleShapeFunctionDerX[4] * segmentShapeFunction[2]; out[14] = triangleShapeFunctionDerX[5] * segmentShapeFunction[2]; out[15] = triangleShapeFunctionDerX[3] * segmentShapeFunction[1]; out[16] = triangleShapeFunctionDerX[4] * segmentShapeFunction[1]; out[17] = triangleShapeFunctionDerX[5] * segmentShapeFunction[1]; break; } case 1: { FieldVector triangleShapeFunctionDerY; triangleShapeFunctionDerY[0] = -3 + 4*(in[0] + in[1]); triangleShapeFunctionDerY[1] = 0; triangleShapeFunctionDerY[2] = -1 + 4* in[1]; triangleShapeFunctionDerY[3] = -4* in[0]; triangleShapeFunctionDerY[4] = 4 - 4* in[0] - 8*in[1]; triangleShapeFunctionDerY[5] = 4* in[0]; FieldVector segmentShapeFunction; segmentShapeFunction[0] = 1 + in[2] * (-3 + 2*in[2]); segmentShapeFunction[1] = in[2] * ( 4 - 4*in[2]); segmentShapeFunction[2] = in[2] * (-1 + 2*in[2]); out[0] = triangleShapeFunctionDerY[0] * segmentShapeFunction[0]; out[1] = triangleShapeFunctionDerY[1] * segmentShapeFunction[0]; out[2] = triangleShapeFunctionDerY[2] * segmentShapeFunction[0]; out[3] = triangleShapeFunctionDerY[0] * segmentShapeFunction[2]; out[4] = triangleShapeFunctionDerY[1] * segmentShapeFunction[2]; out[5] = triangleShapeFunctionDerY[2] * segmentShapeFunction[2]; out[6] = triangleShapeFunctionDerY[0] * segmentShapeFunction[1]; out[7] = triangleShapeFunctionDerY[1] * segmentShapeFunction[1]; out[8] = triangleShapeFunctionDerY[2] * segmentShapeFunction[1]; out[9] = triangleShapeFunctionDerY[3] * segmentShapeFunction[0]; out[10] = triangleShapeFunctionDerY[4] * segmentShapeFunction[0]; out[11] = triangleShapeFunctionDerY[5] * segmentShapeFunction[0]; out[12] = triangleShapeFunctionDerY[3] * segmentShapeFunction[2]; out[13] = triangleShapeFunctionDerY[4] * segmentShapeFunction[2]; out[14] = triangleShapeFunctionDerY[5] * segmentShapeFunction[2]; out[15] = triangleShapeFunctionDerY[3] * segmentShapeFunction[1]; out[16] = triangleShapeFunctionDerY[4] * segmentShapeFunction[1]; out[17] = triangleShapeFunctionDerY[5] * segmentShapeFunction[1]; break; } case 2: { FieldVector triangleShapeFunction; triangleShapeFunction[0] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]); triangleShapeFunction[1] = 2 * in[0] * (-0.5 + in[0]); triangleShapeFunction[2] = 2 * in[1] * (-0.5 + in[1]); triangleShapeFunction[3] = 4*in[0] * (1 - in[0] - in[1]); triangleShapeFunction[4] = 4*in[1] * (1 - in[0] - in[1]); triangleShapeFunction[5] = 4*in[0]*in[1]; FieldVector segmentShapeFunctionDer; segmentShapeFunctionDer[0] = -3 + 4*in[2]; segmentShapeFunctionDer[1] = 4 - 8*in[2]; segmentShapeFunctionDer[2] = -1 + 4*in[2]; out[0] = triangleShapeFunction[0] * segmentShapeFunctionDer[0]; out[1] = triangleShapeFunction[1] * segmentShapeFunctionDer[0]; out[2] = triangleShapeFunction[2] * segmentShapeFunctionDer[0]; out[3] = triangleShapeFunction[0] * segmentShapeFunctionDer[2]; out[4] = triangleShapeFunction[1] * segmentShapeFunctionDer[2]; out[5] = triangleShapeFunction[2] * segmentShapeFunctionDer[2]; out[6] = triangleShapeFunction[0] * segmentShapeFunctionDer[1]; out[7] = triangleShapeFunction[1] * segmentShapeFunctionDer[1]; out[8] = triangleShapeFunction[2] * segmentShapeFunctionDer[1]; out[9] = triangleShapeFunction[3] * segmentShapeFunctionDer[0]; out[10] = triangleShapeFunction[4] * segmentShapeFunctionDer[0]; out[11] = triangleShapeFunction[5] * segmentShapeFunctionDer[0]; out[12] = triangleShapeFunction[3] * segmentShapeFunctionDer[2]; out[13] = triangleShapeFunction[4] * segmentShapeFunctionDer[2]; out[14] = triangleShapeFunction[5] * segmentShapeFunctionDer[2]; out[15] = triangleShapeFunction[3] * segmentShapeFunctionDer[1]; out[16] = triangleShapeFunction[4] * segmentShapeFunctionDer[1]; out[17] = triangleShapeFunction[5] * segmentShapeFunctionDer[1]; break; } default: DUNE_THROW(RangeError, "Component out of range."); } } else { DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } return; } DUNE_THROW(NotImplemented, "LagrangePrismLocalBasis::partial not implemented for order " << k); } //! \brief Polynomial order of the shape functions static constexpr unsigned int order () { return k; } }; /** \brief Associations of the Lagrange degrees of freedom to subentities of the reference prism * * \tparam k Polynomial order of the Lagrange space in one direction */ template class LagrangePrismLocalCoefficients { public: //! \brief Default constructor LagrangePrismLocalCoefficients () : localKeys_(size()) { if (k==0) { localKeys_[0] = LocalKey(0,0,0); return; } if (k==1) { for (std::size_t i=0; i localKeys_; }; /** \brief Evaluate the degrees of freedom of a Lagrange basis * * \tparam LocalBasis The corresponding set of shape functions */ template class LagrangePrismLocalInterpolation { public: /** \brief Evaluate a given function at the Lagrange nodes * * \tparam F Type of function to evaluate * \tparam C Type used for the values of the function * \param[in] ff Function to evaluate * \param[out] out Array of function values */ template void interpolate (const F& ff, std::vector& out) const { constexpr auto dim = LocalBasis::Traits::dimDomain; constexpr auto k = LocalBasis::order(); using D = typename LocalBasis::Traits::DomainType; using DF = typename LocalBasis::Traits::DomainFieldType; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(LocalBasis::size()); // Specialization for zero-order case if (k==0) { auto center = ReferenceElements::general(GeometryTypes::prism).position(0,0); out[0] = f(center); return; } // Specialization for first-order case if (k==1) { for (unsigned int i=0; i::general(GeometryTypes::prism).position(i,3); out[i] = f(vertex); } return; } if (k==2) { out[0] = f( D( {0.0, 0.0, 0.0} ) ); out[1] = f( D( {1.0, 0.0, 0.0} ) ); out[2] = f( D( {0.0, 1.0, 0.0} ) ); out[3] = f( D( {0.0, 0.0, 1.0} ) ); out[4] = f( D( {1.0, 0.0, 1.0} ) ); out[5] = f( D( {0.0, 1.0, 1.0} ) ); out[6] = f( D( {0.0, 0.0, 0.5} ) ); out[7] = f( D( {1.0, 0.0, 0.5} ) ); out[8] = f( D( {0.0, 1.0, 0.5} ) ); out[9] = f( D( {0.5, 0.0, 0.0} ) ); out[10] = f( D( {0.0, 0.5, 0.0} ) ); out[11] = f( D( {0.5, 0.5, 0.0} ) ); out[12] = f( D( {0.5, 0.0, 1.0} ) ); out[13] = f( D( {0.0, 0.5, 1.0} ) ); out[14] = f( D( {0.5, 0.5, 1.0} ) ); out[15] = f( D( {0.5, 0.0, 0.5} ) ); out[16] = f( D( {0.0, 0.5, 0.5} ) ); out[17] = f( D( {0.5, 0.5, 0.5} ) ); return; } DUNE_THROW(NotImplemented, "LagrangePrismLocalInterpolation not implemented for order " << k); } }; } } // namespace Dune::Impl namespace Dune { /** \brief Lagrange finite element for 3d prisms with arbitrary compile-time polynomial order * * \tparam D Type used for domain coordinates * \tparam R Type used for function values * \tparam k Polynomial order */ template class LagrangePrismLocalFiniteElement { public: /** \brief Export number types, dimensions, etc. */ using Traits = LocalFiniteElementTraits, Impl::LagrangePrismLocalCoefficients, Impl::LagrangePrismLocalInterpolation > >; /** \brief Default constructor * * \deprecated This explicit implementation only exists to work around a bug in clang 3.8 * which disappeared in clang 6 */ LagrangePrismLocalFiniteElement() {} /** \brief Returns the local basis, i.e., the set of shape functions */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \brief Returns the assignment of the degrees of freedom to the element subentities */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \brief Returns object that evaluates degrees of freedom */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief The number of shape functions */ static constexpr std::size_t size () { return binomial(k+2,2) * (k+1); } /** \brief The reference element that the local finite element is defined on */ static constexpr GeometryType type () { return GeometryTypes::prism; } private: Impl::LagrangePrismLocalBasis basis_; Impl::LagrangePrismLocalCoefficients coefficients_; Impl::LagrangePrismLocalInterpolation > interpolation_; }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPRISM_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/lagrangepyramid.hh000066400000000000000000001011731411343327200267250ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPYRAMID_HH #define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPYRAMID_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Impl { /** \brief Lagrange shape functions of arbitrary order on the three-dimensional reference pyramid 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 */ template class LagrangePyramidLocalBasis { public: using Traits = LocalBasisTraits,R,1,FieldVector,FieldMatrix >; /** \brief Number of shape functions */ static constexpr std::size_t size () { std::size_t result = 0; for (unsigned int i=0; i<=k; i++) result += power(i+1,2); return result; } //! \brief Evaluate all shape functions void evaluateFunction(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); // Specialization for zero-order case if (k==0) { out[0] = 1; return; } if (k==1) { 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]; return; } if (k==2) { // 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; 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)); } return; } DUNE_THROW(NotImplemented, "LagrangePyramidLocalBasis::evaluateFunction for order " << k); } /** \brief Evaluate Jacobian of all shape functions * * \param x Point in the reference pyramid where to evaluation the Jacobians * \param[out] out The Jacobians of all shape functions at the point x */ void evaluateJacobian(const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); // Specialization for k==0 if (k==0) { std::fill(out[0][0].begin(), out[0][0].end(), 0); return; } if (k==1) { if(in[0] > in[1]) { out[0][0] = {-1 + in[1], -1 + in[0] + in[2], -1 + in[1]}; out[1][0] = { 1 - in[1], -in[0] - in[2], -in[1]}; out[2][0] = { -in[1], 1 - in[0] - in[2], -in[1]}; out[3][0] = { in[1], in[0] + in[2], in[1]}; } else { out[0][0] = {-1 + in[1] + in[2], -1 + in[0], -1 + in[0]}; out[1][0] = { 1 - in[1] - in[2], -in[0], -in[0]}; out[2][0] = { -in[1] - in[2], 1 - in[0], -in[0]}; out[3][0] = { in[1] + in[2], in[0], in[0]}; } out[4][0] = {0, 0, 1}; return; } if (k==2) { // 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)*(2*x + z - 1); out[5][0][1] = -(x + z - 1)*(y - 1)*x - (y - z + 1)*(x + z - 1)*x; out[5][0][2] = 0.5*(out[5][0][0] + out[5][0][1]) + 0.5*(x + z - 1)*(y - 1)*x - 0.5*(y - z + 1)*(y - 1)*x; 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)); } return; } DUNE_THROW(NotImplemented, "LagrangePyramidLocalBasis::evaluateJacobian for order " << k); } /** \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 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); out.resize(size()); if (totalOrder == 0) { evaluateFunction(in, out); return; } if (k==0) { out[0] = 0; return; } if (k==1) { if (totalOrder == 1) { 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) { 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 = {1, -1, -1, 1, 0}; } else { out = {0, 0, 0, 0, 0}; } } else { out = {0, 0, 0, 0, 0}; } return; } if (k==2) { if (totalOrder == 1) { // 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)*(2*x + z - 1)*(y - 1); 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 - (y - z + 1)*(x + z - 1)*x; 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*x + z - 1)*(y - 1) - (x + z - 1)*(y - 1)*x - (y - z + 1)*(x + z - 1)*x + (x + z - 1)*(y - 1)*x - (y - z + 1)*(y - 1)*x)/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"); } return; } DUNE_THROW(NotImplemented, "LagrangePyramidLocalBasis::partial for order " << k); } //! \brief Polynomial order of the shape functions static constexpr unsigned int order () { return k; } }; /** \brief Associations of the Lagrange degrees of freedom to subentities of the reference pyramid * * \tparam k Polynomial order of the Lagrange space in one direction */ template class LagrangePyramidLocalCoefficients { public: //! \brief Default constructor LagrangePyramidLocalCoefficients () : localKeys_(size()) { if (k==0) { localKeys_[0] = LocalKey(0,0,0); return; } if (k==1) { for (std::size_t i=0; i localKeys_; }; /** \brief Evaluate the degrees of freedom of a Lagrange basis * * \tparam LocalBasis The corresponding set of shape functions */ template class LagrangePyramidLocalInterpolation { public: /** \brief Evaluate a given function at the Lagrange nodes * * \tparam F Type of function to evaluate * \tparam C Type used for the values of the function * \param[in] ff Function to evaluate * \param[out] out Array of function values */ template void interpolate (const F& ff, std::vector& out) const { constexpr auto k = LocalBasis::order(); using D = typename LocalBasis::Traits::DomainType; using DF = typename LocalBasis::Traits::DomainFieldType; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(LocalBasis::size()); // Specialization for zero-order case if (k==0) { auto center = ReferenceElements::general(GeometryTypes::pyramid).position(0,0); out[0] = f(center); return; } // Specialization for first-order case if (k==1) { for (unsigned int i=0; i::general(GeometryTypes::pyramid).position(i,3); out[i] = f(vertex); } return; } // Specialization for second-order case if (k==2) { out[0] = f( D( {0.0, 0.0, 0.0} ) ); out[1] = f( D( {1.0, 0.0, 0.0} ) ); out[2] = f( D( {0.0, 1.0, 0.0} ) ); out[3] = f( D( {1.0, 1.0, 0.0} ) ); out[4] = f( D( {0.0, 0.0, 1.0} ) ); out[5] = f( D( {0.0, 0.5, 0.0} ) ); out[6] = f( D( {1.0, 0.5, 0.0} ) ); out[7] = f( D( {0.5, 0.0, 0.0} ) ); out[8] = f( D( {0.5, 1.0, 0.0} ) ); out[9] = f( D( {0.0, 0.0, 0.5} ) ); out[10] = f( D( {0.5, 0.0, 0.5} ) ); out[11] = f( D( {0.0, 0.5, 0.5} ) ); out[12] = f( D( {0.5, 0.5, 0.5} ) ); out[13] = f( D( {0.5, 0.5, 0.0} ) ); return; } DUNE_THROW(NotImplemented, "LagrangePyramidLocalInterpolation not implemented for order " << k); } }; } } // namespace Dune::Impl namespace Dune { /** \brief Lagrange finite element for 3d pyramids with compile-time polynomial order * * \tparam D Type used for domain coordinates * \tparam R Type used for shape function values * \tparam k Polynomial order, only orders 1 and 2 are actually implemented * * Lagrange shape functions are tricky. In the paper mentioned below, Christian Wieners states * "There exists no continuously differentiable conforming shape function for the pyramid * which is linear, resp. bilinear on the faces." * The same holds, mutatis mutandis, for second-order Lagrange functions. * The usual remedy, employed here, is to use shape functions that are continuous, * but only piecewise differentiable. * * More specifically, the implementations in this file are taken from the following papers: * * First order: C. Wieners, Conforming discretizations on tetrahedrons, pyramids, prisms and hexahedrons (1997) * * Second order: L. Liu et.al. On Higher Order Pyramidal Finite Elements, (2011) [anisotropic variant] * * These are piecewise trilinear/triquadratic basis functions with the following properties: * * Shape functions with Lagrange property * * Each basis function is bilinear/biquadratic on the rectangular face * * Each basis function is linear/quadratic on all triangular faces * * Each basis function is continuous in the interelement boundary * * As the derivatives are not continuous, numerical quadrature for expressions involving * shape function derivatives should employ a composite rule composed of two tetrahedral parts. * * \warning The shape functions currently do not sum up to 1, even though my understanding * of the Liu et al. paper is that they should. * */ template class LagrangePyramidLocalFiniteElement { public: /** \brief Export number types, dimensions, etc. */ using Traits = LocalFiniteElementTraits, Impl::LagrangePyramidLocalCoefficients, Impl::LagrangePyramidLocalInterpolation > >; /** \brief Default constructor * * \deprecated This explicit implementation only exists to work around a bug in clang 3.8 * which disappeared in clang 6 */ LagrangePyramidLocalFiniteElement() {} /** \brief Returns the local basis, i.e., the set of shape functions */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \brief Returns the assignment of the degrees of freedom to the element subentities */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \brief Returns object that evaluates degrees of freedom */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief The number of shape functions */ static constexpr std::size_t size () { return Impl::LagrangePyramidLocalBasis::size(); } /** \brief The reference element that the local finite element is defined on */ static constexpr GeometryType type () { return GeometryTypes::pyramid; } private: Impl::LagrangePyramidLocalBasis basis_; Impl::LagrangePyramidLocalCoefficients coefficients_; Impl::LagrangePyramidLocalInterpolation > interpolation_; }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPYRAMID_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/lagrangesimplex.hh000066400000000000000000000675101411343327200267470ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGESIMPLEX_HH #define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGESIMPLEX_HH #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Impl { /** \brief Lagrange shape functions of arbitrary order on the reference simplex 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 dim Dimension of the domain simplex \tparam k Polynomial order */ template class LagrangeSimplexLocalBasis { public: using Traits = LocalBasisTraits,R,1,FieldVector,FieldMatrix >; /** \brief Number of shape functions * * See https://en.wikipedia.org/wiki/Figurate_number for an explanation of the formula */ static constexpr unsigned int size () { return binomial(k+dim,dim); } //! \brief Evaluate all shape functions void evaluateFunction(const typename Traits::DomainType& x, std::vector& out) const { out.resize(size()); // Specialization for zero-order case if (k==0) { out[0] = 1; return; } // Specialization for first-order case if (k==1) { out[0] = 1.0; for (size_t i=0; i=2); auto lagrangeNode = [](unsigned int i) { return ((D)i)/k; }; if (dim==1) { for (unsigned int i=0; i=2 only implemented for dim==1 or dim==3"); 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 * * \param x Point in the reference simplex where to evaluation the Jacobians * \param[out] out The Jacobians of all shape functions at the point x */ void evaluateJacobian(const typename Traits::DomainType& x, std::vector& out) const { out.resize(size()); // Specialization for k==0 if (k==0) { std::fill(out[0][0].begin(), out[0][0].end(), 0); return; } // Specialization for k==1 if (k==1) { std::fill(out[0][0].begin(), out[0][0].end(), -1); for (unsigned int i=0; i& order, const typename Traits::DomainType& in, std::vector& out) const { auto totalOrder = std::accumulate(order.begin(), order.end(), 0); out.resize(size()); if (totalOrder == 0) { evaluateFunction(in, out); return; } if (k==0) { out[0] = 0; return; } if (k==1) { if (totalOrder==1) { auto direction = std::find(order.begin(), order.end(), 1); out[0] = -1; for (unsigned int i=0; i typename Traits::RangeType { if ( no < i) return (x[0]-lagrangeNode(no))/(lagrangeNode(i)-lagrangeNode(no)); if (no < i+j) return (x[1]-lagrangeNode(no-i))/(lagrangeNode(j)-lagrangeNode(no-i)); return (lagrangeNode(no+1)-x[0]-x[1])/(lagrangeNode(no+1)-lagrangeNode(i)-lagrangeNode(j)); }; // Helper method: Return the derivative of a single Lagrangian factor of l_ij evaluated at x // direction: Derive in x-direction if this is 0, otherwise derive in y direction auto lagrangianFactorDerivative = [&lagrangeNode] (const int direction, const int no, const int i, const int j, const typename Traits::DomainType&) -> typename Traits::RangeType { using T = typename Traits::RangeType; if ( no < i) return (direction == 0) ? T(1.0/(lagrangeNode(i)-lagrangeNode(no))) : T(0); if (no < i+j) return (direction == 0) ? T(0) : T(1.0/(lagrangeNode(j)-lagrangeNode(no-i))); return -1.0/(lagrangeNode(no+1)-lagrangeNode(i)-lagrangeNode(j)); }; if (totalOrder==1) { int direction = std::find(order.begin(), order.end(), 1)-order.begin(); 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(direction, no1, i, j, in); for (unsigned int no2=0; no2 < k; no2++) if (no1 != no2) factor *= lagrangianFactor(no2, i, j, in); out[n] += factor; } } } return; } if (totalOrder==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]--; } } //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; } } return; } // totalOrder==2 } // dim==2 DUNE_THROW(NotImplemented, "Desired derivative order is not implemented"); } //! \brief Polynomial order of the shape functions static constexpr unsigned int order () { return k; } }; /** \brief Associations of the Lagrange degrees of freedom to subentities of the reference simplex * * \tparam dim Dimension of the reference simplex * \tparam k Polynomial order of the Lagrange space */ template class LagrangeSimplexLocalCoefficients { public: //! \brief Default constructor LagrangeSimplexLocalCoefficients () : localKeys_(size()) { if (k==0) { localKeys_[0] = LocalKey(0,0,0); return; } if (k==1) { for (std::size_t i=0; i vertexMap; for (unsigned int i=0; i<=dim; i++) vertexMap[i] = i; generateLocalKeys(vertexMap); return; } DUNE_THROW(NotImplemented, "LagrangeSimplexLocalCoefficients only implemented for k<=1 or dim<=3!"); } /** 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...dim */ LagrangeSimplexLocalCoefficients (const std::array vertexMap) : localKeys_(size()) { if (dim!=2 && dim!=3) DUNE_THROW(NotImplemented, "LagrangeSimplexLocalCoefficients only implemented for dim==2 and dim==3!"); generateLocalKeys(vertexMap); } template LagrangeSimplexLocalCoefficients(const VertexMap &vertexmap) : localKeys_(size()) { if (dim!=2 && dim!=3) DUNE_THROW(NotImplemented, "LagrangeSimplexLocalCoefficients only implemented for dim==2 and dim==3!"); std::array vertexmap_array; std::copy(vertexmap, vertexmap + dim + 1, vertexmap_array.begin()); generateLocalKeys(vertexmap_array); } //! number of coefficients static constexpr std::size_t size () { return binomial(k+dim,dim); } //! get i'th index const LocalKey& localKey (std::size_t i) const { return localKeys_[i]; } private: std::vector localKeys_; void generateLocalKeys(const std::array vertexMap) { if (k==0) { localKeys_[0] = LocalKey(0,0,0); return; } if (dim==2) { // Create default assignment 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) { localKeys_[n++] = LocalKey(0,2,0); continue; } if (i==k && j==0) { localKeys_[n++] = LocalKey(1,2,0); continue; } if (i==0 && j==k) { localKeys_[n++] = LocalKey(2,2,0); continue; } if (j==0) { localKeys_[n++] = LocalKey(0,1,i-1); continue; } if (i==0) { localKeys_[n++] = LocalKey(1,1,j-1); continue; } if (i+j==k) { localKeys_[n++] = LocalKey(2,1,j-1); continue; } localKeys_[n++] = LocalKey(0,0,c++); } // Flip edge orientations, if requested 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 class LagrangeSimplexLocalInterpolation { static const int kdiv = (LocalBasis::order() == 0 ? 1 : LocalBasis::order()); public: /** \brief Evaluate a given function at the Lagrange nodes * * \tparam F Type of function to evaluate * \tparam C Type used for the values of the function * \param[in] ff Function to evaluate * \param[out] out Array of function values */ template void interpolate (const F& ff, std::vector& out) const { constexpr auto dim = LocalBasis::Traits::dimDomain; constexpr auto k = LocalBasis::order(); using D = typename LocalBasis::Traits::DomainFieldType; typename LocalBasis::Traits::DomainType x; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(LocalBasis::size()); // Specialization for zero-order case if (k==0) { auto center = ReferenceElements::simplex().position(0,0); out[0] = f(center); return; } // Specialization for first-order case if (k==1) { // vertex 0 std::fill(x.begin(), x.end(), 0); out[0] = f(x); // remaining vertices for (int i=0; i class LagrangeSimplexLocalFiniteElement { public: /** \brief Export number types, dimensions, etc. */ using Traits = LocalFiniteElementTraits, Impl::LagrangeSimplexLocalCoefficients, Impl::LagrangeSimplexLocalInterpolation > >; /** Default-construct the finite element */ LagrangeSimplexLocalFiniteElement() {} /** Constructs a finite element given a vertex reordering * * This version is deprecated - use the std::array variant instead. * */ template LagrangeSimplexLocalFiniteElement(const VertexMap& vertexmap) : coefficients_(vertexmap) {} /** \brief Returns the local basis, i.e., the set of shape functions */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \brief Returns the assignment of the degrees of freedom to the element subentities */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \brief Returns object that evaluates degrees of freedom */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief The number of shape functions */ static constexpr std::size_t size () { return Impl::LagrangeSimplexLocalBasis::size(); } /** \brief The reference element that the local finite element is defined on */ static constexpr GeometryType type () { return GeometryTypes::simplex(d); } private: Impl::LagrangeSimplexLocalBasis basis_; Impl::LagrangeSimplexLocalCoefficients coefficients_; Impl::LagrangeSimplexLocalInterpolation > interpolation_; }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGESIMPLEX_HH dune-localfunctions-2.8.0/dune/localfunctions/lagrange/p0.hh000066400000000000000000000034501411343327200240750ustar00rootroot00000000000000// -*- 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; } private: P0LocalBasis basis; P0LocalCoefficients coefficients; P0LocalInterpolation > interpolation; GeometryType gt; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/p0/000077500000000000000000000000001411343327200235525ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/lagrange/p0/CMakeLists.txt000066400000000000000000000002361411343327200263130ustar00rootroot00000000000000install(FILES p0localbasis.hh p0localcoefficients.hh p0localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/lagrange/p0) dune-localfunctions-2.8.0/dune/localfunctions/lagrange/p0/p0localbasis.hh000066400000000000000000000046301411343327200264520ustar00rootroot00000000000000// -*- 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 > Traits; //! \brief number of shape functions unsigned int size () const { return 1; } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType&, std::vector& out) const { out.resize(1); out[0] = 1; } //! \brief Evaluate Jacobian of all shape functions inline void evaluateJacobian (const typename Traits::DomainType&, // 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.8.0/dune/localfunctions/lagrange/p0/p0localcoefficients.hh000066400000000000000000000015221411343327200300070ustar00rootroot00000000000000// -*- 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 ([[maybe_unused]] std::size_t i) const { return index; } private: LocalKey index; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/p0/p0localinterpolation.hh000066400000000000000000000020241411343327200302330ustar00rootroot00000000000000// -*- 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 #include namespace Dune { template class P0LocalInterpolation { public: P0LocalInterpolation (const GeometryType& gt) : gt_(gt) {} //! determine coefficients interpolating a given function template void interpolate (const F& ff, std::vector& out) const { typedef typename LB::Traits::DomainType DomainType; typedef typename LB::Traits::DomainFieldType DF; const int dim=LB::Traits::dimDomain; auto&& f = Impl::makeFunctionWithCallOperator(ff); DomainType x = Dune::ReferenceElements::general(gt_).position(0,0); out.resize(1); out[0] = f(x); } private: GeometryType gt_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/p1.hh000066400000000000000000000012011411343327200240660ustar00rootroot00000000000000// -*- 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 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 \deprecated This class is obsolete. Please use LagrangeSimplexLocalFiniteElement instead! */ template using P1LocalFiniteElement = LagrangeSimplexLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/p2.hh000066400000000000000000000011041411343327200240710ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_P2_LOCALFINITEELEMENT_HH #define DUNE_P2_LOCALFINITEELEMENT_HH #include namespace Dune { /** \brief Second-order Lagrange finite element on the reference simplex with compile-time dimension \deprecated This class is obsolete. Please use LagrangeSimplexLocalFiniteElement instead! */ template using P2LocalFiniteElement = LagrangeSimplexLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/p23d.hh000066400000000000000000000012521411343327200243240ustar00rootroot00000000000000// -*- 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 namespace Dune { /** \brief Second-order Lagrange local finite element on the reference tetrahedron * * \tparam D Number type used for domain coordinates * \tparam R Number type used for shape function values * * \deprecated This class is obsolete. Please use LagrangeSimplexLocalFiniteElement instead! */ template using P23DLocalFiniteElement = LagrangeSimplexLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/pk.hh000066400000000000000000000006441411343327200241720ustar00rootroot00000000000000// -*- 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 namespace Dune { template using PkLocalFiniteElement = LagrangeSimplexLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/pk1d.hh000066400000000000000000000126561411343327200244250ustar00rootroot00000000000000// -*- 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 namespace Dune { /** \brief Lagrange finite element on the unit interval with arbitrary compile-time order \deprecated This class is obsolete. Please use LagrangeSimplexLocalFiniteElement instead! */ template using Pk1DLocalFiniteElement = LagrangeSimplexLocalFiniteElement; //! 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 Impl::LagrangeSimplexLocalBasis LocalBasis; typedef Impl::LagrangeSimplexLocalInterpolation LocalInterpolation; public: /** * \implements FiniteElementInterface::Traits */ struct Traits { typedef ScalarLocalToGlobalBasisAdaptor Basis; typedef LocalToGlobalInterpolationAdaptor< LocalInterpolation, typename Basis::Traits > Interpolation; typedef Impl::LagrangeSimplexLocalCoefficients<1,k> 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(GeometryTypes::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.8.0/dune/localfunctions/lagrange/pk2d.hh000066400000000000000000000125551411343327200244240ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PK2DLOCALFINITEELEMENT_HH #define DUNE_PK2DLOCALFINITEELEMENT_HH #include #include #include #include #include namespace Dune { /** \todo Please doc me ! \deprecated This class is obsolete. Please use LagrangeSimplexLocalFiniteElement instead! */ template using Pk2DLocalFiniteElement = LagrangeSimplexLocalFiniteElement; //! 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 Impl::LagrangeSimplexLocalBasis LocalBasis; typedef Impl::LagrangeSimplexLocalInterpolation LocalInterpolation; public: /** * \implements FiniteElementInterface::Traits */ struct Traits { typedef ScalarLocalToGlobalBasisAdaptor Basis; typedef LocalToGlobalInterpolationAdaptor< LocalInterpolation, typename Basis::Traits > Interpolation; typedef Impl::LagrangeSimplexLocalCoefficients<2,k> 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(GeometryTypes::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.8.0/dune/localfunctions/lagrange/pk3d.hh000066400000000000000000000010061411343327200244120ustar00rootroot00000000000000// -*- 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 namespace Dune { /** \todo Please doc me ! \deprecated This class is obsolete. Please use LagrangeSimplexLocalFiniteElement instead! */ template using Pk3DLocalFiniteElement = LagrangeSimplexLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/pq22d.hh000066400000000000000000000036741411343327200245160ustar00rootroot00000000000000// -*- 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 namespace Dune { template class PQ22DLocalFiniteElement { using LFEVariant = LocalFiniteElementVariant, LagrangeCubeLocalFiniteElement >; public: using Traits = typename LFEVariant::Traits; PQ22DLocalFiniteElement ( const GeometryType > ) { if ( gt.isTriangle() ) lfeVariant_ = LagrangeSimplexLocalFiniteElement(); else if ( gt.isQuadrilateral() ) lfeVariant_ = LagrangeCubeLocalFiniteElement(); } PQ22DLocalFiniteElement ( const GeometryType >, const std::vector vertexmap ) { if ( gt.isTriangle() ) lfeVariant_ = LagrangeSimplexLocalFiniteElement(vertexmap); else if ( gt.isQuadrilateral() ) lfeVariant_ = LagrangeCubeLocalFiniteElement(); } const typename Traits::LocalBasisType& localBasis () const { return lfeVariant_.localBasis(); } const typename Traits::LocalCoefficientsType& localCoefficients () const { return lfeVariant_.localCoefficients(); } const typename Traits::LocalInterpolationType& localInterpolation () const { return lfeVariant_.localInterpolation(); } /** \brief Number of shape functions in this finite element */ unsigned int size () const { return lfeVariant_.size(); } GeometryType type () const { return lfeVariant_.type(); } private: LFEVariant lfeVariant_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/pqkfactory.hh000066400000000000000000000124161411343327200257430ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_PQKFACTORY_HH #define DUNE_LOCALFUNCTIONS_LAGRANGE_PQKFACTORY_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 P0LocalFiniteElement::Traits::LocalBasisType::Traits T; //! create finite element for given GeometryType static LocalFiniteElementVirtualInterface* create(const GeometryType&) { return nullptr; } }; /** \brief Factory that only creates dimension specific local finite elements * * Specialization for dim=3 */ template struct DimSpecificPQkLocalFiniteElementFactory { typedef typename P0LocalFiniteElement::Traits::LocalBasisType::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 nullptr; } }; /** \brief Factory to create any kind of Pk/Qk like element wrapped for the virtual interface * */ template struct PQkLocalFiniteElementFactory { typedef typename P0LocalFiniteElement::Traits::LocalBasisType::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 P0LocalFiniteElement::Traits::LocalBasisType::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.8.0/dune/localfunctions/lagrange/prismp1.hh000066400000000000000000000010051411343327200251430ustar00rootroot00000000000000// -*- 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 namespace Dune { /** \brief First-order Lagrangian finite element on a prism * * \deprecated Please use LagrangePrismLocalFiniteElement instead! */ template using PrismP1LocalFiniteElement = LagrangePrismLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/prismp2.hh000066400000000000000000000010401411343327200251430ustar00rootroot00000000000000// -*- 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 namespace Dune { /** \brief Second-order Lagrange finite element on a three-dimensional prism * * \deprecated Please use LagrangePrismLocalFiniteElement instead! */ template using PrismP2LocalFiniteElement = LagrangePrismLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/pyramidp1.hh000066400000000000000000000010601411343327200254570ustar00rootroot00000000000000// -*- 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 namespace Dune { /** \brief First-order Lagrangian finite element on a three-dimensional pyramid * * \deprecated Please use LagrangePyramidLocalFiniteElement instead! */ template using PyramidP1LocalFiniteElement = LagrangePyramidLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/pyramidp2.hh000066400000000000000000000010621411343327200254620ustar00rootroot00000000000000// -*- 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 namespace Dune { /** \brief Second-order Lagrangian finite element on a three-dimensional pyramid * * \deprecated Please use LagrangePyramidLocalFiniteElement instead! */ template using PyramidP2LocalFiniteElement = LagrangePyramidLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/q1.hh000066400000000000000000000105511411343327200240770ustar00rootroot00000000000000// -*- 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 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 cube \deprecated This class is deprecated! Please use LagrangeCubeLocalFiniteElement instead. */ // The test test-q1.cc triggers compiler bugs in gcc-6 and earlier when Q1LocalFiniteElement // is simply redefined as LagrangeCubeLocalFiniteElement: it grabs more and more main memory, // and eventually stalls the machine. Since I didn't find the real cause for this let's just // keep the relevant parts of Q1LocalFiniteElement until we can retire the problematic gcc versions. #if !defined __GNUC__ || __GNUC__ > 6 template using Q1LocalFiniteElement = LagrangeCubeLocalFiniteElement; #else template class Q1LocalCoefficients { public: //! \brief Standard constructor Q1LocalCoefficients () : li(1< li; }; template class Q1LocalFiniteElement { public: // user-defined default constructor is required for clang 3.8, // see https://gitlab.dune-project.org/core/dune-localfunctions/merge_requests/60 /** default constructor */ Q1LocalFiniteElement() {} /** \todo Please doc me ! */ typedef LocalFiniteElementTraits,Q1LocalCoefficients, Impl::LagrangeCubeLocalInterpolation > > Traits; /** \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 ! */ static constexpr GeometryType type () { return GeometryTypes::cube(dim); } private: Impl::LagrangeCubeLocalBasis basis; Q1LocalCoefficients coefficients; Impl::LagrangeCubeLocalInterpolation > interpolation; }; #endif //! 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< #if !defined __GNUC__ || __GNUC__ > 6 LagrangeCubeLocalFiniteElement< typename Geometry::ctype, RF, Geometry::mydimension, 1 >, #else Q1LocalFiniteElement< typename Geometry::ctype, RF, Geometry::mydimension >, #endif Geometry > { #if !defined __GNUC__ || __GNUC__ > 6 typedef LagrangeCubeLocalFiniteElement< typename Geometry::ctype, RF, Geometry::mydimension, 1 > LFE; #else typedef Q1LocalFiniteElement< typename Geometry::ctype, RF, Geometry::mydimension > LFE; #endif typedef ScalarLocalToGlobalFiniteElementAdaptorFactory Base; static const LFE lfe; public: //! default constructor Q1FiniteElementFactory() : Base(lfe) {} }; template const typename Q1FiniteElementFactory::LFE Q1FiniteElementFactory::lfe; } #endif dune-localfunctions-2.8.0/dune/localfunctions/lagrange/q2.hh000066400000000000000000000030441411343327200240770ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_Q2_LOCALFINITEELEMENT_HH #define DUNE_Q2_LOCALFINITEELEMENT_HH #include #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.8.0/dune/localfunctions/lagrange/qk.hh000066400000000000000000000015731411343327200241750ustar00rootroot00000000000000// -*- 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 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 * * \deprecated This class is deprecated! Please use LagrangeCubeLocalFiniteElement instead. */ template using QkLocalFiniteElement = LagrangeCubeLocalFiniteElement; } #endif dune-localfunctions-2.8.0/dune/localfunctions/meta/000077500000000000000000000000001411343327200224015ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/meta/CMakeLists.txt000066400000000000000000000001661411343327200251440ustar00rootroot00000000000000add_subdirectory(power) install(FILES power.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/meta) dune-localfunctions-2.8.0/dune/localfunctions/meta/power.hh000066400000000000000000000104721411343327200240620ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/meta/power/000077500000000000000000000000001411343327200235355ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/meta/power/CMakeLists.txt000066400000000000000000000002101411343327200262660ustar00rootroot00000000000000install(FILES basis.hh coefficients.hh interpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/meta/power) dune-localfunctions-2.8.0/dune/localfunctions/meta/power/basis.hh000066400000000000000000000072761411343327200251730ustar00rootroot00000000000000// -*- 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; }; //! 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.8.0/dune/localfunctions/meta/power/coefficients.hh000066400000000000000000000031561411343327200265240ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/meta/power/interpolation.hh000066400000000000000000000066071411343327200267560ustar00rootroot00000000000000// -*- 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 #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_) { } typename Backend::Traits::Range operator()(const typename Backend::Traits::DomainLocal &x) const { typename Traits::Range fy = f(x); typename Backend::Traits::Range y; y[0] = fy[comp]; return y; } }; public: //! Determine coefficients interpolating a given function /** * \param ff An object supporting the expression \c ff.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& ff, std::vector& out) const { auto&& f = Impl::makeFunctionWithCallOperator(ff); out.clear(); std::vector cout; for(std::size_t d = 0; d < Traits::dimRange; ++d) { // When dropping support for `evaluate()` we can simply use a lambda // instead of ComponentEvaluator. But changing this now would break // PowerInterpolation for FE-implementation outside of dune-localfunctions // which may not have been adjusted so far. 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.8.0/dune/localfunctions/mimetic.hh000066400000000000000000000031771411343327200234330ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/mimetic/000077500000000000000000000000001411343327200231025ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/mimetic/CMakeLists.txt000066400000000000000000000001451411343327200256420ustar00rootroot00000000000000install(FILES mimeticall.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/mimetic) dune-localfunctions-2.8.0/dune/localfunctions/mimetic/mimeticall.hh000066400000000000000000000057041411343327200255510ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/monomial.hh000066400000000000000000000140401411343327200236060ustar00rootroot00000000000000// -*- 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 */ template class MonomialLocalFiniteElement { enum { static_size = MonomialLocalBasis::size() }; 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 = Dune::GeometryTypes::vertex; init(gt); break; case 1 : gt = Dune::GeometryTypes::line; init(gt); break; case 2 : gt = Dune::GeometryTypes::triangle; init(gt); gt = Dune::GeometryTypes::quadrilateral; init(gt); break; case 3 : gt = Dune::GeometryTypes::tetrahedron; init(gt); gt = Dune::GeometryTypes::pyramid; init(gt); gt = Dune::GeometryTypes::prism; init(gt); gt = Dune::GeometryTypes::hexahedron; 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.8.0/dune/localfunctions/monomial/000077500000000000000000000000001411343327200232665ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/monomial/CMakeLists.txt000066400000000000000000000002551411343327200260300ustar00rootroot00000000000000install(FILES monomiallocalbasis.hh monomiallocalcoefficients.hh monomiallocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/monomial) dune-localfunctions-2.8.0/dune/localfunctions/monomial/monomiallocalbasis.hh000066400000000000000000000217431411343327200274660ustar00rootroot00000000000000// -*- 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 { //! 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 recurse 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 < (int)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 * power(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 < (int)derivatives[d]) prod = 0; else { int coeff = 1; for(int i = bound - derivatives[d] + 1; i <= bound; ++i) coeff *= i; prod *= power(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 \nosubgrouping */ template class MonomialLocalBasis { // Helper: Number of shape functions for a k-th order element in dimension dd static constexpr unsigned int size (int dd, int k) { if (dd==0 || k==0) return 1; return size(dd,k-1) + size(dd-1,k); } public: //! \brief export type traits for function signature typedef LocalBasisTraits,R,1,Dune::FieldVector, Dune::FieldMatrix > Traits; /** \brief Number of shape functions */ static constexpr unsigned int size () { return size(d,p); } //! \brief Evaluate all shape functions inline void evaluateFunction (const typename Traits::DomainType& in, std::vector& out) const { out.resize(size()); int index = 0; std::array derivatives; std::fill(derivatives.begin(), derivatives.end(), 0); MonomImp::EvalAccess access(out); for (unsigned int lp = 0; lp <= p; ++lp) MonomImp::Evaluate::eval(in, derivatives, 1, lp, index, access); } /** \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 { out.resize(size()); int index = 0; MonomImp::EvalAccess access(out); for (unsigned int lp = 0; lp <= p; ++lp) MonomImp::Evaluate::eval(in, order, 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.8.0/dune/localfunctions/monomial/monomiallocalcoefficients.hh000066400000000000000000000021131411343327200310140ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/monomial/monomiallocalinterpolation.hh000066400000000000000000000055341411343327200312540ustar00rootroot00000000000000// -*- 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 #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& ff, std::vector& out) const { using DomainType = std::decay_tposition())>; auto&& f = Impl::makeFunctionWithCallOperator(ff); 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(qrit->position()); 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.8.0/dune/localfunctions/nedelec.hh000066400000000000000000000007711411343327200234000ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_HH #define DUNE_LOCALFUNCTIONS_NEDELEC_HH // Nedelec element implementations with run-time order // [include them here once they exist] // Nedelec element implementations with compile-time order #include #include #endif // #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_HH dune-localfunctions-2.8.0/dune/localfunctions/nedelec/000077500000000000000000000000001411343327200230525ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/nedelec/CMakeLists.txt000066400000000000000000000002101411343327200256030ustar00rootroot00000000000000install(FILES nedelec1stkindsimplex.hh nedelec1stkindcube.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/nedelec) dune-localfunctions-2.8.0/dune/localfunctions/nedelec/nedelec1stkindcube.hh000066400000000000000000000430571411343327200271400ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_NEDELEC1STKINDCUBE_HH #define DUNE_LOCALFUNCTIONS_NEDELEC_NEDELEC1STKINDCUBE_HH #include #include #include #include #include #include #include #include #include // For deprecated makeFunctionWithCallOperator #include namespace Dune { namespace Impl { /** \brief Nedelec shape functions of the first kind on reference cubes * * \note These shape functions are implemented for the reference cubes only! * The transformation to other cubes has to be done by the user. * * \tparam D Number type used for domain coordinates * \tparam R Number type used for function values * \tparam dim Dimension of the reference element * \tparam k Order of the Nedelec element */ template class Nedelec1stKindCubeLocalBasis { // Number of edges of the reference cube constexpr static std::size_t numberOfEdges = power(2,dim-1)*dim; public: using Traits = LocalBasisTraits, R,dim,FieldVector, FieldMatrix >; /** \brief Constructor with default edge orientation * * Default orientation means that all edges point from the vertex with lower index * to the vertex with higher index. The tangential parts of all shape functions * point in the direction of the edge. */ Nedelec1stKindCubeLocalBasis() { std::fill(edgeOrientation_.begin(), edgeOrientation_.end(), 1.0); } /** \brief Constructor for a given edge orientation */ Nedelec1stKindCubeLocalBasis(std::bitset edgeOrientation) : Nedelec1stKindCubeLocalBasis() { for (std::size_t i=0; i& out) const { static_assert(k==1, "Evaluating Nédélec shape functions is implemented only for first order."); out.resize(size()); if (dim==2) { // First-order Nédélec shape functions on a square are of the form // // (a, b)^T + (c y, d x)^T, a, b, c, d \in R // // The following coefficients create the four basis vectors // that are dual to the edge degrees of freedom: // // a[0] = 0 b[0] = 1 c[0] = 0 d[0] = -1 // a[1] = 0 b[1] = 0 c[1] = 0 d[1] = 1 // a[2] = 1 b[2] = 0 c[2] = 0 d[2] = -1 // a[3] = 0 b[3] = 0 c[3] = 0 d[3] = 1 out[0] = { 0, D(1) - in[0]}; out[1] = { 0, in[0]}; out[2] = { D(1) - in[1], 0}; out[3] = { in[1], 0}; } if constexpr (dim==3) { // First-order Nédélec shape functions on a cube are of the form // // (e1 yz) // a + b x + c y + d z + (e2 xz) , a, b, c, d \in R^3 and b[0]=c[1]=d[2]=0 // (e3 xy) // // The following coefficients create the twelve basis vectors // that are dual to the edge degrees of freedom: // // a[0] = { 0, 0, 1} b[0] = { 0, 0, -1} c[0] = { 0, 0, -1} d[0] = { 0, 0, 0} e[0] = { 0, 0, 1} // a[1] = { 0, 0, 0} b[1] = { 0, 0, 1} c[1] = { 0, 0, 0} d[1] = { 0, 0, 0} e[1] = { 0, 0, -1} // a[2] = { 0, 0, 0} b[2] = { 0, 0, 0} c[2] = { 0, 0, 1} d[2] = { 0, 0, 0} e[2] = { 0, 0, -1} // a[3] = { 0, 0, 0} b[3] = { 0, 0, 0} c[3] = { 0, 0, 0} d[3] = { 0, 0, 0} e[3] = { 0, 0, 1} // // The following implementation uses these values, and simply // skips all the zeros. for (std::size_t i=0; i& out) const { out.resize(size()); if (dim==2) { for (std::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) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); if (dim==2) { if (direction==0) { out[0] = { 0, -1}; out[1] = { 0, 1}; out[2] = { 0, 0}; out[3] = { 0, 0}; } else { out[0] = { 0, 0}; out[1] = { 0, 0}; out[2] = { -1, 0}; out[3] = { 1, 0}; } } if (dim==3) { switch (direction) { case 0: out[0] = { 0, 0, -1 +in[1]}; out[1] = { 0, 0, 1 -in[1]}; out[2] = { 0, 0, -in[1]}; out[3] = { 0, 0, in[1]}; out[4] = { 0, -1 +in[2], 0}; out[5] = { 0, 1 -in[2], 0}; out[8] = { 0, -in[2], 0}; out[9] = { 0, in[2], 0}; out[6] = {0,0,0}; out[7] = {0,0,0}; out[10] = {0,0,0}; out[11] = {0,0,0}; break; case 1: out[0] = { 0, 0, -1 + in[0]}; out[1] = { 0, 0, - in[0]}; out[2] = { 0, 0, 1 - in[0]}; out[3] = { 0, 0, in[0]}; out[4] = {0,0,0}; out[5] = {0,0,0}; out[8] = {0,0,0}; out[9] = {0,0,0}; out[6] = { -1 + in[2], 0, 0}; out[7] = { 1 - in[2], 0, 0}; out[10] = { - in[2], 0, 0}; out[11] = { in[2], 0, 0}; break; case 2: out[0] = {0,0,0}; out[1] = {0,0,0}; out[2] = {0,0,0}; out[3] = {0,0,0}; out[4] = { 0, -1 + in[0], 0}; out[5] = { 0, - in[0], 0}; out[8] = { 0, 1 - in[0], 0}; out[9] = { 0, in[0], 0}; out[6] = { -1 + in[1], 0, 0}; out[7] = { - in[1], 0, 0}; out[10] = { 1 - in[1], 0, 0}; out[11] = { in[1], 0, 0}; break; } } for (std::size_t i=0; i edgeOrientation_; }; /** \brief Assignment of Nedelec degrees of freedom to subentities of the reference cube * \tparam dim Dimension of the domain * \tparam k Order of the Nedelec finite element */ template class Nedelec1stKindCubeLocalCoefficients { public: //! \brief Default constructor Nedelec1stKindCubeLocalCoefficients () : localKey_(size()) { static_assert(k==1, "Only first-order Nédélec local coefficients are implemented."); // Assign all degrees of freedom to edges // TODO: This is correct only for first-order Nédélec elements for (std::size_t i=0; i localKey_; }; /** \brief Project a given function into the Nedelec space * * \tparam LB The LocalBasis that spans the space */ template class Nedelec1stKindCubeLocalInterpolation { static constexpr auto dim = LB::Traits::dimDomain; static constexpr auto size = LB::size(); // Number of edges of the reference cube constexpr static std::size_t numberOfEdges = power(2,dim-1)*dim; public: //! \brief Constructor with given set of edge orientations Nedelec1stKindCubeLocalInterpolation (std::bitset s = 0) { auto refElement = Dune::referenceElement(GeometryTypes::cube(dim)); for (std::size_t i=0; iv1) std::swap(v0,v1); edge_[i] = refElement.position(v1,dim) - refElement.position(v0,dim); edge_[i] *= (s[i]) ? -1.0 : 1.0; } } /** \brief Project a given function into the Nedelec space * * \param f The function to interpolate, must implement RangeField operator(DomainType) * \param[out] out The coefficients of the projection */ template void interpolate (const F& ff, std::vector& out) const { out.resize(size); auto&& f = Impl::makeFunctionWithCallOperator(ff); for (std::size_t i=0; i m_; // Edges of the reference cube std::array edge_; }; } /** * \brief Nédélec elements of the first kind for cube elements * * These elements have been described in : * * J.C. Nédélec, "Mixed finite elements in R^3", Numer.Math., 35(3):315-341,1980. * DOI: http://dx.doi.org/10.1007/BF01396415 * * The order count starts at '1'. This is the counting used, e.g., by Nédélec himself, * and by Kirby, Logg, Rognes, Terrel, "Common and unusual finite elements", * https://doi.org/10.1007/978-3-642-23099-8_3 * * \note These shape functions are implemented for the reference cube only! * The transformation to other cubes has to be done by the user. * * \ingroup Nedelec * * \tparam D Number type used for domain coordinates * \tparam R Number type use for shape function values * \tparam dim Dimension of the domain * \tparam k Order of the Nedelec finite element (lowest is 1) * */ template class Nedelec1stKindCubeLocalFiniteElement { public: using Traits = LocalFiniteElementTraits, Impl::Nedelec1stKindCubeLocalCoefficients, Impl::Nedelec1stKindCubeLocalInterpolation > >; static_assert(dim==2 || dim==3, "Nedelec elements are only implemented for 2d and 3d elements."); static_assert(k==1, "Nedelec elements of the first kind are currently only implemented for order k==1."); /** \brief Default constructor */ Nedelec1stKindCubeLocalFiniteElement() = default; /** * \brief Constructor with explicitly given edge orientations * * \param s Edge orientation indicator */ Nedelec1stKindCubeLocalFiniteElement (std::bitset s) : basis_(s), interpolation_(s) {} const typename Traits::LocalBasisType& localBasis () const { return basis_; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } static constexpr unsigned int size () { return Traits::LocalBasisType::size(); } static constexpr GeometryType type () { return GeometryTypes::cube(dim); } private: typename Traits::LocalBasisType basis_; typename Traits::LocalCoefficientsType coefficients_; typename Traits::LocalInterpolationType interpolation_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/nedelec/nedelec1stkindsimplex.hh000066400000000000000000000345211411343327200276770ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_NEDELEC1STKINDSIMPLEX_HH #define DUNE_LOCALFUNCTIONS_NEDELEC_NEDELEC1STKINDSIMPLEX_HH #include #include #include #include #include #include #include #include // For deprecated makeFunctionWithCallOperator #include namespace Dune { namespace Impl { /** \brief Nedelec shape functions of the first kind on reference simplices * * \note These shape functions are implemented for the reference simplices only! * The transformation to other simplices has to be done by the user. * * \tparam D Number type used for domain coordinates * \tparam R Number type used for function values * \tparam dim Dimension of the reference element * \tparam k Order of the Nedelec element */ template class Nedelec1stKindSimplexLocalBasis { // Number of edges of the reference simplex constexpr static std::size_t numberOfEdges = dim*(dim+1)/2; public: using Traits = LocalBasisTraits, R,dim,FieldVector, FieldMatrix >; /** \brief Constructor with default edge orientation * * Default orientation means that all edges point from the vertex with lower index * to the vertex with higher index. The tangential parts of all shape functions * point in the direction of the edge. */ Nedelec1stKindSimplexLocalBasis() { std::fill(edgeOrientation_.begin(), edgeOrientation_.end(), 1.0); } /** \brief Constructor for a given edge orientation */ Nedelec1stKindSimplexLocalBasis(std::bitset edgeOrientation) : Nedelec1stKindSimplexLocalBasis() { for (std::size_t i=0; i& out) const { static_assert(k==1, "Evaluating Nédélec shape functions is implemented only for first order."); out.resize(size()); if (dim==2) { // First-order Nédélec shape functions on a triangle are of the form // // (a1, a2) + b(-x2, x1)^T, a_1, a_2, b \in R out[0] = {D(1) - in[1], in[0]}; out[1] = {in[1], -in[0]+D(1)}; out[2] = {-in[1], in[0]}; } if constexpr (dim==3) { // First-order Nédélec shape functions on a tetrahedron are of the form // // a + b \times x, a, b \in R^3 // // The following coefficients create the six basis vectors // that are dual to the edge degrees of freedom: // // a[0] = { 1, 0, 0} b[0] = { 0, -1, 1} // a[1] = { 0, 1, 0} b[1] = { 1, 0, -1} // a[2] = { 0, 0, 0} b[2] = { 0, 0, 1} // a[3] = { 0, 0, 1} b[3] = {-1, 1, 0} // a[4] = { 0, 0, 0} b[4] = { 0, -1, 0} // a[5] = { 0, 0, 0} b[5] = { 1, 0, 0} // // The following implementation uses these values, and simply // skips all the zeros. out[0] = { 1 - in[1] - in[2], in[0] , in[0] }; out[1] = { in[1] , 1 - in[0] - in[2], in[1]}; out[2] = { - in[1] , in[0] , 0 }; out[3] = { in[2], in[2], 1 - in[0] - in[1]}; out[4] = { -in[2], 0 , in[0] }; out[5] = { 0 , -in[2], in[1]}; } for (std::size_t i=0; i& out) const { out.resize(size()); if (dim==2) { out[0][0] = { 0, -1}; out[0][1] = { 1, 0}; out[1][0] = { 0, 1}; out[1][1] = {-1, 0}; out[2][0] = { 0, -1}; out[2][1] = { 1, 0}; } if (dim==3) { out[0][0] = { 0,-1,-1}; out[0][1] = { 1, 0, 0}; out[0][2] = { 1, 0, 0}; out[1][0] = { 0, 1, 0}; out[1][1] = {-1, 0, -1}; out[1][2] = { 0, 1, 0}; out[2][0] = { 0, -1, 0}; out[2][1] = { 1, 0, 0}; out[2][2] = { 0, 0, 0}; out[3][0] = { 0, 0, 1}; out[3][1] = { 0, 0, 1}; out[3][2] = {-1, -1, 0}; out[4][0] = { 0, 0, -1}; out[4][1] = { 0, 0, 0}; out[4][2] = { 1, 0, 0}; out[5][0] = { 0, 0, 0}; out[5][1] = { 0, 0, -1}; out[5][2] = { 0, 1, 0}; } for (std::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) { auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1)); out.resize(size()); if (dim==2) { if (direction==0) { out[0] = {0, 1}; out[1] = {0, -1}; out[2] = {0, 1}; } else { out[0] = {-1, 0}; out[1] = { 1, 0}; out[2] = {-1, 0}; } } if (dim==3) { switch (direction) { case 0: out[0] = { 0, 1, 1}; out[1] = { 0,-1, 0}; out[2] = { 0, 1, 0}; out[3] = { 0, 0,-1}; out[4] = { 0, 0, 1}; out[5] = { 0, 0, 0}; break; case 1: out[0] = {-1, 0, 0}; out[1] = { 1, 0, 1}; out[2] = {-1, 0, 0}; out[3] = { 0, 0,-1}; out[4] = { 0, 0, 0}; out[5] = { 0, 0, 1}; break; case 2: out[0] = {-1, 0, 0}; out[1] = { 0,-1, 0}; out[2] = { 0, 0, 0}; out[3] = { 1, 1, 0}; out[4] = {-1, 0, 0}; out[5] = { 0,-1, 0}; break; } } for (std::size_t i=0; i edgeOrientation_; }; /** \brief Assignment of Nedelec degrees of freedom to subentities of the reference simplex * \tparam dim Dimension of the domain * \tparam k Order of the Nedelec finite element */ template class Nedelec1stKindSimplexLocalCoefficients { public: //! \brief Default constructor Nedelec1stKindSimplexLocalCoefficients () : localKey_(size()) { static_assert(k==1, "Only first-order Nédélec local coefficients are implemented."); // Assign all degrees of freedom to edges // TODO: This is correct only for first-order Nédélec elements for (std::size_t i=0; i localKey_; }; /** \brief Project a given function into the Nedelec space * * \tparam LB The LocalBasis that spans the space */ template class Nedelec1stKindSimplexLocalInterpolation { static constexpr auto dim = LB::Traits::dimDomain; static constexpr auto size = LB::size(); // Number of edges of the reference simplex constexpr static std::size_t numberOfEdges = dim*(dim+1)/2; public: //! \brief Constructor with given set of edge orientations Nedelec1stKindSimplexLocalInterpolation (std::bitset s = 0) { auto refElement = Dune::referenceElement(GeometryTypes::simplex(dim)); for (std::size_t i=0; iv1) std::swap(v0,v1); edge_[i] = refElement.position(v1,dim) - refElement.position(v0,dim); edge_[i] *= (s[i]) ? -1.0 : 1.0; } } /** \brief Project a given function into the Nedelec space * * \param f The function to interpolate, must implement RangeField operator(DomainType) * \param[out] out The coefficients of the projection */ template void interpolate (const F& ff, std::vector& out) const { out.resize(size); auto&& f = Impl::makeFunctionWithCallOperator(ff); for (std::size_t i=0; i m_; // Edges of the reference simplex std::array edge_; }; } /** * \brief Nédélec elements of the first kind for simplex elements * * These elements have been described in : * * J.C. Nédélec, "Mixed finite elements in R^3", Numer.Math., 35(3):315-341,1980. * DOI: http://dx.doi.org/10.1007/BF01396415 * * The order count starts at '1'. This is the counting used, e.g., by Nédélec himself, * and by Kirby, Logg, Rognes, Terrel, "Common and unusual finite elements", * https://doi.org/10.1007/978-3-642-23099-8_3 * * \note These shape functions are implemented for the reference simplices only! * The transformation to other simplices has to be done by the user. * One way of doing that is using the implementation of the covariant * Piola transform in globalvaluedlocalfinitelement.hh in dune-functions. * * \ingroup Nedelec * * \tparam D Number type used for domain coordinates * \tparam R Number type use for shape function values * \tparam dim Dimension of the domain * \tparam k Order of the Nedelec finite element (lowest is 1) * */ template class Nedelec1stKindSimplexLocalFiniteElement { public: using Traits = LocalFiniteElementTraits, Impl::Nedelec1stKindSimplexLocalCoefficients, Impl::Nedelec1stKindSimplexLocalInterpolation > >; static_assert(dim==2 || dim==3, "Nedelec elements are only implemented for 2d and 3d elements."); static_assert(k==1, "Nedelec elements of the first kind are currently only implemented for order k==1."); /** \brief Default constructor */ Nedelec1stKindSimplexLocalFiniteElement() = default; /** * \brief Constructor with explicitly given edge orientations * * \param s Edge orientation indicator */ Nedelec1stKindSimplexLocalFiniteElement (std::bitset s) : basis_(s), interpolation_(s) {} const typename Traits::LocalBasisType& localBasis () const { return basis_; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } static constexpr unsigned int size () { return Traits::LocalBasisType::size(); } static constexpr GeometryType type () { return GeometryTypes::simplex(dim); } private: typename Traits::LocalBasisType basis_; typename Traits::LocalCoefficientsType coefficients_; typename Traits::LocalInterpolationType interpolation_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/nedelec/nedelecsimplex/000077500000000000000000000000001411343327200260535ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/nedelec/nedelecsimplex/CMakeLists.txt000066400000000000000000000002721411343327200306140ustar00rootroot00000000000000install(FILES nedelecsimplexbasis.hh nedelecsimplexinterpolation.hh nedelecsimplexprebasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/nedelec/nedelecsimplex) dune-localfunctions-2.8.0/dune/localfunctions/nedelec/nedelecsimplex/nedelecsimplexbasis.hh000066400000000000000000000031171411343327200324210ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXBASIS_HH #define DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXBASIS_HH #include #include #include #include "nedelecsimplexinterpolation.hh" #include "nedelecsimplexprebasis.hh" namespace Dune { /* * `NedelecPreBasisFactory` provides a basis for the Nedelec function space. * `NedelecL2InterpolationFactory` provides the linear functionals. * * `Defaultbasisfactory::create` first builds the function space and the linear functionals. * Then the constructor of `BasisMatrix` gets called. There the matrix * * \begin{equation} * A_{i,j} := N_j(\phi_i) * \end{equation} * * with linear functionals $N_j$ and basisfunctions $\phi_i$ gets assembled. * Then the matrix gets inverted and is then used as a coefficent matrix for the standard monomial basis. * * For more details on the theory see the first chapter "Construction of Local Finite Element Spaces Using the Generic Reference Elements" * of the book "Advances in Dune" by Dedner, Flemisch and Klöfkorn published in 2012. */ template< unsigned int dim, class SF, class CF > struct NedelecBasisFactory : public DefaultBasisFactory< NedelecPreBasisFactory, NedelecL2InterpolationFactory, dim,dim,SF,CF > {}; } #endif // #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXBASIS_HH dune-localfunctions-2.8.0/dune/localfunctions/nedelec/nedelecsimplex/nedelecsimplexinterpolation.hh000066400000000000000000000551361411343327200342170ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXINTERPOLATION_HH #include #include #include #include #include #include #include #include #include #include #include namespace Dune { // Internal Forward Declarations // ----------------------------- template < unsigned int dim, class Field > struct NedelecL2InterpolationFactory; // 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 ]; } std::size_t size () const { return localKey_.size(); } private: std::vector< LocalKey > localKey_; }; // NedelecCoefficientsFactory // -------------------------------- template < unsigned int dim > struct NedelecCoefficientsFactory { typedef std::size_t Key; typedef const LocalCoefficientsContainer Object; template< GeometryType::Id geometryId > static Object *create( const Key &key ) { typedef NedelecL2InterpolationFactory< dim, double > InterpolationFactory; if( !supports< geometryId >( key ) ) return nullptr; typename InterpolationFactory::Object *interpolation = InterpolationFactory::template create< geometryId >( key ); Object *localKeys = new Object( *interpolation ); InterpolationFactory::release( interpolation ); return localKeys; } template< GeometryType::Id geometryId > static bool supports ( const Key &key ) { GeometryType gt = geometryId; return gt.isTriangle() || gt.isTetrahedron() ; } static void release( Object *object ) { delete object; } }; // NedelecL2InterpolationBuilder // ------------------------ // L2 Interpolation requires: // - for element // - test basis // - for each face (dynamic) // - test basis // - tangents // - for each edge (dynamic) // - test basis // - tangent template< unsigned int dim, class Field > struct NedelecL2InterpolationBuilder { static const unsigned int dimension = dim; // for the dofs associated to the element typedef OrthonormalBasisFactory< dimension, Field > TestBasisFactory; typedef typename TestBasisFactory::Object TestBasis; // for the dofs associated to the faces typedef OrthonormalBasisFactory< dimension-1, Field > TestFaceBasisFactory; typedef typename TestFaceBasisFactory::Object TestFaceBasis; // for the dofs associated to the edges typedef OrthonormalBasisFactory< 1, Field > TestEdgeBasisFactory; typedef typename TestEdgeBasisFactory::Object TestEdgeBasis; // the tangent of the edges typedef FieldVector< Field, dimension > Tangent; // the normal and the tangents of the faces typedef FieldVector< Field, dimension > Normal; typedef std::array,dim-1> FaceTangents; NedelecL2InterpolationBuilder () = default; NedelecL2InterpolationBuilder ( const NedelecL2InterpolationBuilder & ) = delete; NedelecL2InterpolationBuilder ( NedelecL2InterpolationBuilder && ) = delete; ~NedelecL2InterpolationBuilder () { TestBasisFactory::release( testBasis_ ); for( FaceStructure &f : faceStructure_ ) TestFaceBasisFactory::release( f.basis_ ); for( EdgeStructure& e : edgeStructure_ ) TestEdgeBasisFactory::release( e.basis_ ); } unsigned int topologyId () const { return geometry_.id(); } GeometryType type () const { return geometry_; } std::size_t order () const { return order_; } // number of faces unsigned int faceSize () const { return numberOfFaces_; } // number of edges unsigned int edgeSize () const { return numberOfEdges_; } // basis associated to the element TestBasis *testBasis () const { return testBasis_; } // basis associated to face f TestFaceBasis *testFaceBasis ( unsigned int f ) const { assert( f < faceSize() ); return faceStructure_[ f ].basis_; } // basis associated to edge e TestEdgeBasis *testEdgeBasis ( unsigned int e ) const { assert( e < edgeSize() ); return edgeStructure_[ e ].basis_; } const Tangent& edgeTangent ( unsigned int e ) const { assert( e < edgeSize() ); return edgeStructure_[ e ].tangent_; } const FaceTangents& faceTangents ( unsigned int f ) const { assert( f < faceSize() ); return faceStructure_[ f ].faceTangents_; } const Normal &normal ( unsigned int f ) const { assert( f < faceSize() ); return faceStructure_[ f ].normal_; } template< GeometryType::Id geometryId > void build ( std::size_t order ) { constexpr GeometryType geometry = geometryId; order_ = order; geometry_ = geometry; /* * The Nedelec parameter begins at 1. * This is the numbering used by J.C. Nedelec himself. * See "Mixed Finite Elements in \R^3" published in 1980. * * This construction is based on the construction of Raviart-Thomas elements. * There the numbering starts at 0. * Because of this we reduce the order internally by 1. */ order--; // if dimension == 2: order-1 on element // if dimension == 3: order-2 on element int requiredOrder = static_cast(dimension==3); testBasis_ = (order > requiredOrder ? TestBasisFactory::template create< geometry >( order-1-requiredOrder ) : nullptr); const auto &refElement = ReferenceElements< Field, dimension >::general( type() ); numberOfFaces_ = refElement.size( 1 ); faceStructure_.reserve( numberOfFaces_ ); // compute the basis, tangents and normals of each face for (std::size_t i=0; i zero(0); FaceTangents faceTangents; faceTangents.fill(zero); // use the first dim-1 vertices of a face to compute the tangents auto vertices = refElement.subEntities(i,1,dim).begin(); auto vertex1 = *vertices; for(int j=1; jvertex2) faceTangents[j-1] *=-1; vertex1 = vertex2; } /* For simplices or cubes of arbitrary dimension you could just use * * ``` * GeometryType faceGeometry = Impl::getBase(geometry_); * TestFaceBasis *faceBasis = ( dim == 3 && order > 0 ? TestFaceBasisFactory::template create< faceGeometry >( order-1 ) : nullptr); * ``` * * For i.e. Prisms and Pyramids in 3d this does not work because they contain squares and triangles as faces. * And depending on the dynamic face index a different face geometry is needed. * */ TestFaceBasis *faceBasis = ( dim == 3 && order > 0 ? Impl::IfGeometryType< CreateFaceBasis, dimension-1 >::apply( refElement.type( i, 1 ), order-1 ) : nullptr); faceStructure_.emplace_back( faceBasis, refElement.integrationOuterNormal(i), faceTangents ); } assert( faceStructure_.size() == numberOfFaces_ ); numberOfEdges_ = refElement.size( dim-1 ); edgeStructure_.reserve( numberOfEdges_ ); // compute the basis and tangent of each edge for (std::size_t i=0; iv1) std::swap(v0,v1); auto tangent = std::move(refElement.position(v1,dim) - refElement.position(v0,dim)); TestEdgeBasis *edgeBasis = Impl::IfGeometryType< CreateEdgeBasis, 1 >::apply( refElement.type( i, dim-1 ), order ); edgeStructure_.emplace_back( edgeBasis, tangent ); } assert( edgeStructure_.size() == numberOfEdges_ ); } private: // helper struct for edges struct EdgeStructure { EdgeStructure( TestEdgeBasis *teb, const Tangent &t ) : basis_( teb ), tangent_( t ) {} TestEdgeBasis *basis_; const Dune::FieldVector< Field, dimension > tangent_; }; template< GeometryType::Id edgeGeometryId > struct CreateEdgeBasis { static TestEdgeBasis *apply ( std::size_t order ) { return TestEdgeBasisFactory::template create< edgeGeometryId >( order ); } }; // helper struct for faces struct FaceStructure { FaceStructure( TestFaceBasis *tfb, const Normal& normal, const FaceTangents& faceTangents ) : basis_( tfb ), normal_(normal), faceTangents_( faceTangents ) {} TestFaceBasis *basis_; const Dune::FieldVector< Field, dimension > normal_; const FaceTangents faceTangents_; }; template< GeometryType::Id faceGeometryId > struct CreateFaceBasis { static TestFaceBasis *apply ( std::size_t order ) { return TestFaceBasisFactory::template create< faceGeometryId >( order ); } }; TestBasis *testBasis_ = nullptr; std::vector< FaceStructure > faceStructure_; unsigned int numberOfFaces_; std::vector< EdgeStructure > edgeStructure_; unsigned int numberOfEdges_; GeometryType geometry_; std::size_t order_; }; // NedelecL2Interpolation // ---------------------------- /** * \class NedelecL2Interpolation * \brief An L2-based interpolation for Nedelec * **/ template< unsigned int dimension, class F> class NedelecL2Interpolation : public InterpolationHelper< F ,dimension > { typedef NedelecL2Interpolation< dimension, F > This; typedef InterpolationHelper Base; public: typedef F Field; typedef NedelecL2InterpolationBuilder Builder; typedef typename Builder::FaceTangents FaceTangents; NedelecL2Interpolation() : order_(0), size_(0) {} template< class Function, class Vector > auto interpolate ( const Function &function, Vector &coefficients ) const -> std::enable_if_t< std::is_same< decltype(std::declval().resize(1) ),void >::value,void> { coefficients.resize(size()); typename Base::template Helper func( function,coefficients ); interpolate(func); } template< class Basis, class Matrix > auto interpolate ( const Basis &basis, Matrix &matrix ) const -> std::enable_if_t< std::is_same< decltype(std::declval().rowPtr(0)), typename Matrix::Field* >::value,void> { matrix.resize( size(), basis.size() ); typename Base::template Helper func( basis,matrix ); interpolate(func); } std::size_t order() const { return order_; } std::size_t size() const { return size_; } template void build( std::size_t order ) { size_ = 0; order_ = order; builder_.template build(order_); if (builder_.testBasis()) size_ += dimension*builder_.testBasis()->size(); for ( unsigned int f=0; fsize(); for ( unsigned int e=0; esize(); } void setLocalKeys(std::vector< LocalKey > &keys) const { keys.resize(size()); unsigned int row = 0; for (unsigned int e=0; esize(); ++i,++row) keys[row] = LocalKey(e,dimension-1,i); } for (unsigned int f=0; fsize()*(dimension-1); ++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 testBasisVal; for (unsigned int i=0; i EdgeQuadrature; typedef Dune::QuadratureRules EdgeQuadratureRules; const auto &refElement = Dune::ReferenceElements< Field, dimension >::general( geoType ); for (unsigned int e=0; esize()); const auto &geometry = refElement.template geometry< dimension-1 >( e ); const Dune::GeometryType subGeoType( geometry.type().id(), 1 ); const EdgeQuadrature &edgeQuad = EdgeQuadratureRules::rule( subGeoType, 2*order_+2 ); const unsigned int quadratureSize = edgeQuad.size(); for( unsigned int qi = 0; qi < quadratureSize; ++qi ) { if (dimension>1) builder_.testEdgeBasis(e)->template evaluate<0>(edgeQuad[qi].position(),testBasisVal); else testBasisVal[0] = 1.; computeEdgeDofs(row, testBasisVal, func.evaluate( geometry.global( edgeQuad[qi].position() ) ), builder_.edgeTangent(e), edgeQuad[qi].weight(), func); } row += builder_.testEdgeBasis(e)->size(); } // face dofs: typedef Dune::QuadratureRule FaceQuadrature; typedef Dune::QuadratureRules FaceQuadratureRules; for (unsigned int f=0; fsize()); const auto &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.; computeFaceDofs( row, testBasisVal, func.evaluate( geometry.global( faceQuad[qi].position() ) ), builder_.faceTangents(f), builder_.normal(f), faceQuad[qi].weight(), func); } row += builder_.testFaceBasis(f)->size()*(dimension-1); } } // 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); computeInteriorDofs(row, testBasisVal, func.evaluate(elemQuad[qi].position()), elemQuad[qi].weight(), func ); } row += builder_.testBasis()->size()*dimension; } assert(row==size()); } private: /** /brief evaluate functionals associated to the edges * * \param startRow row of matrix to start * \param mVal value of the testBasis at a quadrature point on an edge * \param nedVal value of the nedelecBasis at a quadrature point on an edge * \param tangent the tangent of the edge * \param weight quadrature weight * \param matrix result gets written into matrix starting with row: row */ template void computeEdgeDofs (unsigned int startRow, const MVal &mVal, const NedVal &nedVal, const FieldVector &tangent, const Field &weight, Matrix &matrix) const { const unsigned int endRow = startRow+mVal.size(); typename NedVal::const_iterator nedIter = nedVal.begin(); for ( unsigned int col = 0; col < nedVal.size() ; ++nedIter,++col) { Field cFactor = (*nedIter)*tangent; 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() ); } } /** /brief evaluate functionals associated to the faces * * \param startRow row of matrix to start * \param mVal value of the testBasis at a quadrature point on a face * \param nedVal value of the nedelecBasis at a quadrature point on a face * \param faceTangents the tangents of the face * \param normal the normal of the face * \param weight quadrature weight * \param matrix result gets written into matrix starting with row: row */ template void computeFaceDofs (unsigned int startRow, const MVal &mVal, const NedVal &nedVal, const FaceTangents& faceTangents, const FieldVector &normal, const Field &weight, Matrix &matrix) const { const unsigned int endRow = startRow+mVal.size()*(dimension-1); typename NedVal::const_iterator nedIter = nedVal.begin(); for ( unsigned int col = 0; col < nedVal.size() ; ++nedIter,++col) { auto const& u=*nedIter; auto const& n=normal; FieldVector nedTimesNormal = { u[1]*n[2]-u[2]*n[1], u[2]*n[0]-u[0]*n[2], u[0]*n[1]-u[1]*n[0]}; typename MVal::const_iterator mIter = mVal.begin(); for (unsigned int row = startRow; row!=endRow; ++mIter) { for(int i=0; i void computeInteriorDofs (unsigned int startRow, const MVal &mVal, const NedVal &nedVal, Field weight, Matrix &matrix) const { const unsigned int endRow = startRow+mVal.size()*dimension; typename NedVal::const_iterator nedIter = nedVal.begin(); for ( unsigned int col = 0; col < nedVal.size() ; ++nedIter,++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 NedelecL2InterpolationFactory { typedef NedelecL2InterpolationBuilder Builder; typedef const NedelecL2Interpolation Object; typedef std::size_t Key; typedef typename std::remove_const::type NonConstObject; template static Object *create( const Key &key ) { if ( !supports(key) ) return 0; NonConstObject *interpol = new NonConstObject(); interpol->template build(key); return interpol; } template static bool supports( const Key &key ) { GeometryType gt = geometryId; return gt.isTriangle() || gt.isTetrahedron() ; } static void release( Object *object ) { delete object; } }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXINTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/nedelec/nedelecsimplex/nedelecsimplexprebasis.hh000066400000000000000000000206031411343327200331270ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXPREBASIS_HH #define DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXPREBASIS_HH #include #include #include #include namespace Dune { template < GeometryType::Id geometryId, class Field > struct NedelecVecMatrix; template struct NedelecPreBasisFactory { typedef MonomialBasisProvider MBasisFactory; typedef typename MBasisFactory::Object MBasis; typedef StandardEvaluator EvalMBasis; typedef PolynomialBasisWithMatrix > Basis; typedef const Basis Object; typedef std::size_t Key; template struct EvaluationBasisFactory { typedef MonomialBasisProvider Type; }; template< GeometryType::Id geometryId > static Object *create ( Key order ) { /* * The nedelec parameter begins at 1. * This is the numbering used by J.C. Nedelec himself. * See "Mixed Finite Elements in \R^3" published in 1980. * * This construction is based on the construction of Raviart-Thomas elements. * There the numbering starts at 0. * Because of this we reduce the order internally by 1. */ order--; NedelecVecMatrix vecMatrix(order); MBasis *mbasis = MBasisFactory::template create(order+1); std::remove_const_t* tmBasis = new std::remove_const_t(*mbasis); tmBasis->fill(vecMatrix); return tmBasis; } static void release( Object *object ) { delete object; } }; template struct NedelecVecMatrix { static constexpr GeometryType geometry = geometryId; static const unsigned int dim = geometry.dim(); typedef MultiIndex MI; typedef MonomialBasis MIBasis; NedelecVecMatrix(std::size_t order) { /* * Construction of Nedelec elements see "Mixed Finite Elements in \R^3" by Nedelec, 1980. * * Let $\P_{n,k}$ be the space of polynomials in $n$ variables with degree $\leq k$. * The space of Nedelec functions in $n$ dimensions with index $k$ is defined as * * \begin{equation*} * Ned_k := (\P_{n,k-1})^n \oplus \{p \in (\P_{n,k})^n: =0 \} * \end{equation*} * with $x=(x,y)$ in two dimensions and $x=(x,y,z)$ in three dimensions. * * For $Ned_k$ holds * \begin{equation*} * (\P_{n,k-1})^n \subset Ned_k \subset (\P_{n,k})^n. * \end{equation*} * * We construct $(\P_{n,k})^n$ and and only use the monomials contained in $Ned$. * */ if( dim!=2 && dim!=3 || !geometry.isSimplex()) DUNE_THROW(Dune::NotImplemented,"High order nedelec elements are only supported by simplices in 2d and 3d"); MIBasis basis(order+1); FieldVector< MI, dim > x; /* * Init MultiIndices * x[0]=(1,0,0) x * x[1]=(0,1,0) y * x[2]=(0,0,1) z */ for( unsigned int i = 0; i < dim; ++i ) x[i].set(i,1); std::vector< MI > val( basis.size() ); // val now contains all monomials in $n$ dimensions with degree $\leq order+1$ basis.evaluate( x, val ); col_ = basis.size(); // get $\dim (\P_{n,order-1})$ unsigned int notHomogen = 0; if (order>0) notHomogen = basis.sizes()[order-1]; // the number of basis functions for the set of homogeneous polynomials with degree $order$ unsigned int homogen = basis.sizes()[order]-notHomogen; /* * 2D: * \begin{equation*} * Ned_{order} = (\P_{order-1})^2 \oplus (-y,x)^T \widetilde \P_{order-1} * \end{equation*} * * It gets more complicated in higher dimensions. * * 3D: * \begin{equation*} * Ned_{order} = (\P_{n,order-1})^3 \oplus (z,0,-x)^T \widetilde \P_{n,order-1} \oplus (-y,x,0)^T \widetilde \P_{n,order-1} \oplus (0,-z,y)^T \widetilde \P_{n-1,order-1} * \end{equation*} * * Note the last term. The index $n-1$ is on purpose. * Else i.e. k=2 * * (0,z,-y)^T x = (z,0,-x)^T y - (y,-x,0)^T z. * */ /* * compute the number of rows for the coefficient matrix * * row_ = dim* \dim Ned_{order} */ if (dim == 2) row_ = (notHomogen*dim+homogen*(dim+1))*dim; else if (dim==3) { // get dim \P_{n-1,order-1} int homogenTwoVariables = 0; for( int w = notHomogen; w0; /* * Init 9 rows to zero. * If the homogeneous monomial has a positive x-exponent (0,-z,y) gets skipped ( see example for the Nedelec space in 3D ) * In this case only 6 rows get initialised. */ for (unsigned int r=0; r 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 #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.8.0/dune/localfunctions/orthonormal/000077500000000000000000000000001411343327200240175ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/orthonormal/CMakeLists.txt000066400000000000000000000002071411343327200265560ustar00rootroot00000000000000install(FILES orthonormalbasis.hh orthonormalcompute.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/orthonormal) dune-localfunctions-2.8.0/dune/localfunctions/orthonormal/orthonormalbasis.hh000066400000000000000000000035561411343327200277370ustar00rootroot00000000000000// -*- 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 namespace Dune { // OrthonormalBasisFactory // ----------------------- template< int dim, class SF, class CF = typename ComputeField< SF, 512 >::Type > struct OrthonormalBasisFactory { static const unsigned int dimension = dim; typedef SF StorageField; typedef CF ComputeField; 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 unsigned int Key; typedef const Basis Object; static constexpr GeometryType SimplexGeometry = GeometryTypes::simplex(dim); template< GeometryType::Id geometryId > static Object *create ( const unsigned int order ) { const MonomialBasisType &monomialBasis = *MonomialBasisProviderType::template create< SimplexGeometry >( order ); static CoefficientMatrix _coeffs; if( _coeffs.size() <= monomialBasis.size() ) { ONBCompute::ONBMatrix< geometryId, ComputeField > matrix( order ); _coeffs.fill( matrix ); } return new Basis( monomialBasis, _coeffs, monomialBasis.size() ); } static void release( Object *object ) { delete object; } }; } #endif // #ifndef DUNE_ORTHONORMALBASIS_HH dune-localfunctions-2.8.0/dune/localfunctions/orthonormal/orthonormalcompute.hh000066400000000000000000000123621411343327200303050ustar00rootroot00000000000000// -*- 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 #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< Dune::GeometryType::Id geometryId > struct Integral { static constexpr Dune::GeometryType geometry = geometryId; static constexpr int dimension = geometry.dim(); template< int dim, class scalar_t > static int compute ( const Dune::MultiIndex< dim, scalar_t > &alpha, scalar_t &p, scalar_t &q ) { return compute(alpha, p, q, std::make_integer_sequence{}); } template< int dim, class scalar_t , int ...ints> static int compute ( const Dune::MultiIndex< dim, scalar_t > &alpha, scalar_t &p, scalar_t &q, std::integer_sequence intS) { p = scalar_t( 1 ); q = scalar_t( 1 ); int ord = 0; ((computeIntegral(alpha,p,q,ord)),...); return ord; } template< int step, int dim, class scalar_t > static void computeIntegral ( const Dune::MultiIndex< dim, scalar_t > &alpha, scalar_t &p, scalar_t &q, int& ord) { int i = alpha.z( step ); if constexpr ( geometry.isPrismatic(step)) { //p *= scalar_t( 1 ); q *= scalar_t( i+1 ); } else { p *= factorial< scalar_t >( 1, i ); q *= factorial< scalar_t >( step+1 + ord, step+1 + ord + i ); } ord +=i; } }; // ONBMatrix // --------- template< Dune::GeometryType::Id geometryId, class scalar_t > class ONBMatrix : public Dune::LFEMatrix< scalar_t > { typedef ONBMatrix< geometryId, 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 constexpr Dune::GeometryType geometry = geometryId; constexpr unsigned int dim = geometry.dim(); 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< geometryId >::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 () { using std::sqrt; // 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.8.0/dune/localfunctions/rannacherturek.hh000066400000000000000000000004161411343327200250110ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/rannacherturek/000077500000000000000000000000001411343327200244675ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/rannacherturek/CMakeLists.txt000066400000000000000000000004721411343327200272320ustar00rootroot00000000000000add_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.8.0/dune/localfunctions/rannacherturek/rannacherturek.hh000066400000000000000000000037441411343327200300340ustar00rootroot00000000000000// -*- 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 GeometryTypes::cube(d); } 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.8.0/dune/localfunctions/rannacherturek/rannacherturek2d/000077500000000000000000000000001411343327200277315ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/rannacherturek/rannacherturek2d/CMakeLists.txt000066400000000000000000000002151411343327200324670ustar00rootroot00000000000000install(FILES rannacherturek2dlocalbasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/rannacherturek/rannacherturek2d) rannacherturek2dlocalbasis.hh000066400000000000000000000073221411343327200354760ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.8.0/dune/localfunctions/rannacherturek/rannacherturek3d/000077500000000000000000000000001411343327200277325ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/rannacherturek/rannacherturek3d/CMakeLists.txt000066400000000000000000000002151411343327200324700ustar00rootroot00000000000000install(FILES rannacherturek3dlocalbasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/rannacherturek/rannacherturek3d) rannacherturek3dlocalbasis.hh000066400000000000000000000104311411343327200354730ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.8.0/dune/localfunctions/rannacherturek/rannachertureklocalbasis.hh000066400000000000000000000017441411343327200320670ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/rannacherturek/rannachertureklocalcoefficients.hh000066400000000000000000000026461411343327200334310ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/rannacherturek/rannachertureklocalinterpolation.hh000066400000000000000000000031561411343327200336540ustar00rootroot00000000000000// -*- 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 #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 &ff, std::vector< C > &out ) const { typedef typename Traits::DomainType DomainType; auto&& f = Impl::makeFunctionWithCallOperator(ff); // get cubic reference element auto 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 ); out[ i ] = f(x); } } }; } // namespace Dune #endif // #ifndef DUNE_RANNACHER_TUREK_LOCALINTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas.hh000066400000000000000000000021071411343327200246600ustar00rootroot00000000000000// -*- 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 // Raviart-Thomas implementations with run-time order #include #include // Raviart-Thomas implementations with compile-time order #include #include #include #include #include #include #include #include #include #endif // #ifndef DUNE_RAVIARTTHOMASFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/000077500000000000000000000000001411343327200243375ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/CMakeLists.txt000066400000000000000000000015011411343327200270740ustar00rootroot00000000000000add_subdirectory(raviartthomas02d) add_subdirectory(raviartthomas03d) 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 raviartthomas03d.hh raviartthomas0cube2d.hh raviartthomas0cube3d.hh raviartthomas12d.hh raviartthomas1cube2d.hh raviartthomas1cube3d.hh raviartthomas2cube2d.hh raviartthomas3cube2d.hh raviartthomas4cube2d.hh raviartthomascube.hh raviartthomaslfecache.hh raviartthomassimplex.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas) dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas02d.hh000066400000000000000000000036011411343327200300520ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Constructor with explicitly given edge orientations * * \param s Edge orientation indicator */ RT02DLocalFiniteElement (std::bitset<3> s) : basis(s), interpolation(s) {} const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } unsigned int size () const { return 3; } static constexpr GeometryType type () { return GeometryTypes::triangle; } private: RT02DLocalBasis basis; RT02DLocalCoefficients coefficients; RT02DLocalInterpolation > interpolation; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas02d/000077500000000000000000000000001411343327200275315ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas02d/CMakeLists.txt000066400000000000000000000003331411343327200322700ustar00rootroot00000000000000install(FILES raviartthomas02dlocalbasis.hh raviartthomas02dlocalcoefficients.hh raviartthomas02dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas02d) raviartthomas02dlocalbasis.hh000066400000000000000000000057111411343327200352260ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 Make set number s, where 0 <= s < 8 RT02DLocalBasis (std::bitset<3> s = 0) { for (int i=0; i<3; i++) sign_[i] = s[i] ? -1.0 : 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] = {sign_[0]*in[0], sign_[0]*(in[1]-D(1))}; out[1] = {sign_[1]*(in[0]-D(1)), sign_[1]*in[1]}; out[2] = {sign_[2]*in[0], sign_[2]*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); for (int i=0; i<3; i++) { out[i][0] = {sign_[i], 0}; out[i][1] = { 0, sign_[i]}; } } //! \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 (int i=0; i<3; i++) { out[i][direction] = sign_[i]; out[i][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: // Signs of the edge normals std::array sign_; }; } #endif raviartthomas02dlocalcoefficients.hh000066400000000000000000000016521411343327200365660ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000034071411343327200370140ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #include #include namespace Dune { template class RT02DLocalInterpolation { public: //! \brief Constructor with given set of edge orientations RT02DLocalInterpolation (std::bitset<3> s = 0) { using std::sqrt; for (std::size_t i=0; i void interpolate (const F& ff, std::vector& out) const { // f gives v*outer normal at a point on the edge! auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(3); for (int i=0; i<3; i++) { auto y = f(m_[i]); out[i] = (y[0]*n_[i][0]+y[1]*n_[i][1])*sign_[i]/c_[i]; } } private: // Edge orientations std::array sign_; // Edge midpoints of the reference triangle std::array m_; // Unit outer normals of the reference triangle std::array n_; // Inverse triangle edge length std::array c_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas03d.hh000066400000000000000000000036331411343327200300600ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMAS03D_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMAS03D_HH #include #include #include "raviartthomas03d/raviartthomas03dlocalbasis.hh" #include "raviartthomas03d/raviartthomas03dlocalcoefficients.hh" #include "raviartthomas03d/raviartthomas03dlocalinterpolation.hh" namespace Dune { /** * \brief Zero order Raviart-Thomas shape functions on tetrahedra. * * \ingroup RaviartThomas * * \tparam D Type to represent the field in the domain. * \tparam R Type to represent the field in the range. */ template class RT03DLocalFiniteElement { public: typedef LocalFiniteElementTraits,RT03DLocalCoefficients, RT03DLocalInterpolation > > Traits; //! \brief Standard constructor RT03DLocalFiniteElement () {} /** * \brief Constructor with explicitly given face orientations * * \param s Face orientation indicator */ RT03DLocalFiniteElement (std::bitset<4> s) : basis(s), interpolation(s) {} const typename Traits::LocalBasisType& localBasis () const { return basis; } const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients; } const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation; } unsigned int size () const { return 4; } static constexpr GeometryType type () { return GeometryTypes::tetrahedron; } private: RT03DLocalBasis basis; RT03DLocalCoefficients coefficients; RT03DLocalInterpolation > interpolation; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas03d/000077500000000000000000000000001411343327200275325ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas03d/CMakeLists.txt000066400000000000000000000003331411343327200322710ustar00rootroot00000000000000install(FILES raviartthomas03dlocalbasis.hh raviartthomas03dlocalcoefficients.hh raviartthomas03dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas03d) raviartthomas03dlocalbasis.hh000066400000000000000000000066741411343327200352410ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas03d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMAS03D_RAVIARTTHOMAS03DLOCALBASIS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMAS03D_RAVIARTTHOMAS03DLOCALBASIS_HH #include #include #include namespace Dune { /**@ingroup LocalBasisImplementation \brief Lowest order Raviart-Thomas shape functions on the reference tetrahedron. \tparam D Type to represent the field in the domain. \tparam R Type to represent the field in the range. \nosubgrouping */ template class RT03DLocalBasis { public: typedef LocalBasisTraits,R,3,Dune::FieldVector, Dune::FieldMatrix > Traits; //! \brief Make set number s, where 0 <= s < 16 RT03DLocalBasis (std::bitset<4> s = 0) { for (int i=0; i<4; i++) sign_[i] = s[i] ? -1.0 : 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); auto c = std::sqrt(2.0); out[0] = {sign_[0]*c* in[0], sign_[0]*c* in[1], sign_[0]*c*(in[2]-D(1))}; out[1] = {sign_[1]*c* in[0], sign_[1]*c*(in[1]-D(1)), sign_[1]*c* in[2] }; out[2] = {sign_[2]*c*(in[0]-D(1)), sign_[2]*c* in[1], sign_[2]*c* in[2] }; out[3] = {sign_[3]*c* in[0], sign_[3]*c* in[1], sign_[3]*c* 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(4); for (int i=0; i<4; i++) { auto c = std::sqrt(2.0); out[i][0] = {c*sign_[i], 0, 0}; out[i][1] = { 0,c*sign_[i], 0}; out[i][2] = { 0, 0,c*sign_[i]}; } } //! \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 (int i=0; i sign_; }; } #endif raviartthomas03dlocalcoefficients.hh000066400000000000000000000020201411343327200365560ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas03d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMAS03D_RAVIARTTHOMAS03DLOCALCOEFFICIENTS_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMAS03D_RAVIARTTHOMAS03DLOCALCOEFFICIENTS_HH #include #include #include #include namespace Dune { /**@ingroup LocalLayoutImplementation \brief Layout map for RT0 elements \nosubgrouping \implements Dune::LocalCoefficientsVirtualImp */ class RT03DLocalCoefficients { public: //! \brief Standard constructor RT03DLocalCoefficients () : 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 raviartthomas03dlocalinterpolation.hh000066400000000000000000000040631411343327200370150ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas03d// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMAS03D_RAVIARTTHOMAS03DLOCALINTERPOLATION_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMAS03D_RAVIARTTHOMAS03DLOCALINTERPOLATION_HH #include #include #include #include #include namespace Dune { template class RT03DLocalInterpolation { public: //! \brief Constructor with given set of face orientations RT03DLocalInterpolation (std::bitset<4> s = 0) { using std::sqrt; for (std::size_t i=0; i void interpolate (const F& ff, std::vector& out) const { // f gives v*outer normal at a point on the face! auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(4); for (int i=0; i<4; i++) { auto y = f(m_[i]); out[i] = (y[0]*n_[i][0]+y[1]*n_[i][1]+y[2]*n_[i][2])*sign_[i]/c_[i]; } } private: // Face orientations std::array sign_; // Face midpoints of the reference tetrahedron std::array m_; // Unit outer normals of the reference tetrahedron std::array n_; // Inverse triangle face area std::array c_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas0cube2d.hh000066400000000000000000000035061411343327200307150ustar00rootroot00000000000000// -*- 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 () {} RT0Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::quadrilateral; } private: RT0Cube2DLocalBasis basis; RT0Cube2DLocalCoefficients coefficients; RT0Cube2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas0cube2d/000077500000000000000000000000001411343327200303705ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas0cube2d/CMakeLists.txt000066400000000000000000000002151411343327200331260ustar00rootroot00000000000000install(FILES raviartthomas0cube2dall.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas0cube2d) raviartthomas0cube2dall.hh000066400000000000000000000134121411343327200353550ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 Constructor with a set of edge orientations RT0Cube2DLocalBasis (std::bitset<4> s = 0) { for (int i=0; i<4; i++) sign_[i] = s[i] ? -1.0 : 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] = {sign_[0]*(in[0]-1.0), 0.0}; out[1] = {sign_[1]*(in[0]), 0.0}; out[2] = {0.0, sign_[2]*(in[1]-1.0)}; out[3] = {0.0, sign_[3]*(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] = {sign_[0], 0}; out[0][1] = {0, 0}; out[1][0] = {sign_[1], 0}; out[1][1] = {0, 0}; out[2][0] = {0, 0}; out[2][1] = {0, sign_[2]}; out[3][0] = {0, 0}; out[3][1] = {0, sign_[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) { 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, 0}; switch (direction) { case 0: out[0][0] = sign_[0]; out[1][0] = sign_[1]; break; case 1: out[2][1] = sign_[2]; out[3][1] = sign_[3]; 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: std::array sign_; }; /**@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 Constructor with explicitly given edge orientations RT0Cube2DLocalInterpolation (std::bitset<4> s = 0) { for (int i=0; i<4; i++) sign_[i] = s[i] ? -1.0 : 1.0; m0 = {0.0, 0.5}; m1 = {1.0, 0.5}; m2 = {0.5, 0.0}; m3 = {0.5, 1.0}; n0 = {-1.0, 0.0}; n1 = { 1.0, 0.0}; n2 = { 0.0, -1.0}; n3 = { 0.0, 1.0}; } template void interpolate (const F& ff, std::vector& out) const { // f gives v*outer normal at a point on the edge! auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(4); // Evaluate the normal components at the edge midpoints auto y = f(m0); out[0] = (y[0]*n0[0]+y[1]*n0[1])*sign_[0]; y = f(m1); out[1] = (y[0]*n1[0]+y[1]*n1[1])*sign_[1]; y = f(m2); out[2] = (y[0]*n2[0]+y[1]*n2[1])*sign_[2]; y = f(m3); out[3] = (y[0]*n3[0]+y[1]*n3[1])*sign_[3]; } private: std::array sign_; // The four edge midpoints of the reference quadrilateral typename LB::Traits::DomainType m0,m1,m2,m3; // The four edge normals of the reference quadrilateral 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.8.0/dune/localfunctions/raviartthomas/raviartthomas0cube3d.hh000066400000000000000000000034761411343327200307240ustar00rootroot00000000000000// -*- 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 () {} RT0Cube3DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::hexahedron; } private: RT0Cube3DLocalBasis basis; RT0Cube3DLocalCoefficients coefficients; RT0Cube3DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS0_CUBE3D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas0cube3d/000077500000000000000000000000001411343327200303715ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas0cube3d/CMakeLists.txt000066400000000000000000000002151411343327200331270ustar00rootroot00000000000000install(FILES raviartthomas0cube3dall.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas0cube3d) raviartthomas0cube3dall.hh000066400000000000000000000176421411343327200353700ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 Make set number s, where 0 <= s < 64 RT0Cube3DLocalBasis (unsigned int s = 0) { 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 Make set number s, where 0 <= s < 64 RT0Cube3DLocalInterpolation (unsigned int s = 0) { 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& ff, std::vector& out) const { // f gives v*outer normal at a point on the edge! auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(6); auto y = f(m0); out[0] = (y[0]*n0[0]+y[1]*n0[1]+y[2]*n0[2])*sign0; y = f(m1); out[1] = (y[0]*n1[0]+y[1]*n1[1]+y[2]*n1[2])*sign1; y = f(m2); out[2] = (y[0]*n2[0]+y[1]*n2[1]+y[2]*n2[2])*sign2; y = f(m3); out[3] = (y[0]*n3[0]+y[1]*n3[1]+y[2]*n3[2])*sign3; y = f(m4); out[4] = (y[0]*n4[0]+y[1]*n4[1]+y[2]*n4[2])*sign4; y = f(m5); 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.8.0/dune/localfunctions/raviartthomas/raviartthomas12d.hh000066400000000000000000000037771411343327200300710ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT12DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::triangle; } private: RT12DLocalBasis basis; RT12DLocalCoefficients coefficients; RT12DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas12d/000077500000000000000000000000001411343327200275325ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas12d/CMakeLists.txt000066400000000000000000000003331411343327200322710ustar00rootroot00000000000000install(FILES raviartthomas12dlocalbasis.hh raviartthomas12dlocalcoefficients.hh raviartthomas12dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas12d) raviartthomas12dlocalbasis.hh000066400000000000000000000154171411343327200352340ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT12DLocalBasis (std::bitset<3> s = 0) { 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 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] - 4.0*in[0]*in[1]); out[0][1] = sign_[0]*(-1.0 + 5.0*in[1] - 4.0*in[1]*in[1]); out[1][0] = sign_[1]*(-1.0 + 5.0*in[0] - 4.0*in[0]*in[0]); out[1][1] = sign_[1]*(in[1] - 4.0*in[0]*in[1]); out[2][0] = sign_[2]*(-3.0*in[0] + 4.0*in[0]*in[0] + 4.0*in[1]*in[0]); out[2][1] = sign_[2]*(-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] = sign_[0]*(1.0 - 4.0*in[1]); out[0][0][1] = sign_[0]*(-4.0*in[0]); out[0][1][0] = 0.0; out[0][1][1] = sign_[0]*(5.0 - 8.0*in[1]); out[1][0][0] = sign_[1]*(5.0 - 8.0*in[0]); out[1][0][1] = 0.0; out[1][1][0] = sign_[1]*(-4.0*in[1]); out[1][1][1] = sign_[1]*(1.0 - 4.0*in[0]); out[2][0][0] = sign_[2]*(-3.0 + 8.0*in[0] + 4.0*in[1]); out[2][0][1] = sign_[2]*(4.0*in[0]); out[2][1][0] = sign_[2]*(4.0*in[1]); out[2][1][1] = sign_[2]*(-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] = sign_[0]*(1.0 - 4.0*in[1]); out[0][1] = 0.0; out[1][0] = sign_[1]*(5.0 - 8.0*in[0]); out[1][1] = sign_[1]*(-4.0*in[1]); out[2][0] = sign_[2]*(-3.0 + 8.0*in[0] + 4.0*in[1]); out[2][1] = sign_[2]*(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] = sign_[2]*(-3.0 + 4.0*in[0] + 8.0*in[1]); out[2][0] = sign_[2]*(4.0*in[0]); out[1][1] = sign_[1]*(1.0 - 4.0*in[0]); out[1][0] = 0.0; out[0][0] = sign_[0]*(-4.0*in[0]); out[0][1] = sign_[0]*(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: std::array sign_; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALBASIS_HH raviartthomas12dlocalcoefficients.hh000066400000000000000000000022471411343327200365710ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000066571411343327200370300ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 Make set number s, where 0 <= s < 8 * * \param s Edge orientation indicator */ RT12DLocalInterpolation (std::bitset<3> s = 0) { using std::sqrt; for (size_t i=0; i<3; i++) sign_[i] = (s[i]) ? -1.0 : 1.0; n_[0] = { 0.0, -1.0}; n_[1] = {-1.0, 0.0}; n_[2] = { 1.0/sqrt(2.0), 1.0/sqrt(2.0)}; c_ = { 0.5*n_[0][0] - 1.0*n_[0][1], -1.0*n_[1][0] + 0.5*n_[1][1], 0.5*n_[2][0] + 0.5*n_[2][1]}; } /** * \brief Interpolate a given function with shape functions * * \tparam F Function type for function which should be interpolated * \tparam C Coefficient type * \param ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(8); fill(out.begin(), out.end(), 0.0); const int qOrder1 = 4; const auto& rule1 = Dune::QuadratureRules::rule(Dune::GeometryTypes::simplex(1), qOrder1); for (auto&& qp : rule1) { Scalar qPos = qp.position(); typename LB::Traits::DomainType localPos; localPos = {qPos, 0.0}; auto y = f(localPos); out[0] += (y[0]*n_[0][0] + y[1]*n_[0][1])*qp.weight()*sign_[0]/c_[0]; out[3] += (y[0]*n_[0][0] + y[1]*n_[0][1])*(2.0*qPos - 1.0)*qp.weight()/c_[0]; localPos = {0.0, qPos}; y = f(localPos); out[1] += (y[0]*n_[1][0] + y[1]*n_[1][1])*qp.weight()*sign_[1]/c_[1]; out[4] += (y[0]*n_[1][0] + y[1]*n_[1][1])*(1.0 - 2.0*qPos)*qp.weight()/c_[1]; localPos = {1.0 - qPos, qPos}; y = f(localPos); out[2] += (y[0]*n_[2][0] + y[1]*n_[2][1])*qp.weight()*sign_[2]/c_[2]; out[5] += (y[0]*n_[2][0] + y[1]*n_[2][1])*(2.0*qPos - 1.0)*qp.weight()/c_[2]; } const int qOrder2 = 8; const auto& rule2 = Dune::QuadratureRules::rule(Dune::GeometryTypes::simplex(2), qOrder2); for (auto&& qp : rule2) { auto qPos = qp.position(); auto y = f(qPos); out[6] += y[0]*qp.weight(); out[7] += y[1]*qp.weight(); } } private: // Edge orientations std::array sign_; // Edge normals std::array n_; std::array c_; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS12DLOCALINTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas1cube2d.hh000066400000000000000000000041571411343327200307210ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT1Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::quadrilateral; } private: RT1Cube2DLocalBasis basis; RT1Cube2DLocalCoefficients coefficients; RT1Cube2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas1cube2d/000077500000000000000000000000001411343327200303715ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas1cube2d/CMakeLists.txt000066400000000000000000000003531411343327200331320ustar00rootroot00000000000000install(FILES raviartthomas1cube2dlocalbasis.hh raviartthomas1cube2dlocalcoefficients.hh raviartthomas1cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas1cube2d) raviartthomas1cube2dlocalbasis.hh000066400000000000000000000133551411343327200367310ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT1Cube2DLocalBasis (std::bitset<4> s = 0) { 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 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] = sign_[0]*(-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] = sign_[1]*(-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] = sign_[2]*(-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] = sign_[3]*(-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] = sign_[0]*(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] = sign_[1]*(-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] = sign_[2]*(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] = sign_[3]*(-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: std::array sign_; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALBASIS_HH raviartthomas1cube2dlocalcoefficients.hh000066400000000000000000000023441411343327200402650ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000066541411343327200405230ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT1Cube2DLocalInterpolation (std::bitset<4> s = 0) { for (size_t i=0; i<4; i++) sign_[i] = (s[i]) ? -1.0 : 1.0; n_[0] = {-1.0, 0.0}; n_[1] = { 1.0, 0.0}; n_[2] = { 0.0, -1.0}; n_[3] = { 0.0, 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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(12); fill(out.begin(), out.end(), 0.0); const int qOrder = 3; const auto& rule1 = QuadratureRules::rule(GeometryTypes::cube(1), qOrder); for (auto&& qp : rule1) { Scalar qPos = qp.position(); typename LB::Traits::DomainType localPos = {0.0, qPos}; auto y = f(localPos); out[0] += (y[0]*n_[0][0] + y[1]*n_[0][1])*qp.weight()*sign_[0]; out[1] += (y[0]*n_[0][0] + y[1]*n_[0][1])*(2.0*qPos - 1.0)*qp.weight(); localPos = {1.0, qPos}; y = f(localPos); out[2] += (y[0]*n_[1][0] + y[1]*n_[1][1])*qp.weight()*sign_[1]; out[3] += (y[0]*n_[1][0] + y[1]*n_[1][1])*(1.0 - 2.0*qPos)*qp.weight(); localPos = {qPos, 0.0}; y = f(localPos); out[4] += (y[0]*n_[2][0] + y[1]*n_[2][1])*qp.weight()*sign_[2]; out[5] += (y[0]*n_[2][0] + y[1]*n_[2][1])*(1.0 - 2.0*qPos)*qp.weight(); localPos = {qPos, 1.0}; y = f(localPos); out[6] += (y[0]*n_[3][0] + y[1]*n_[3][1])*qp.weight()*sign_[3]; out[7] += (y[0]*n_[3][0] + y[1]*n_[3][1])*(2.0*qPos - 1.0)*qp.weight(); } const auto& rule2 = QuadratureRules::rule(GeometryTypes::cube(2), qOrder); for (auto&& qp : rule2) { auto qPos = qp.position(); auto y = f(qPos); out[8] += y[0]*qp.weight(); out[9] += y[1]*qp.weight(); out[10] += y[0]*qPos[1]*qp.weight(); out[11] += y[1]*qPos[0]*qp.weight(); } } private: // Edge orientations std::array sign_; // Edge normals std::array n_; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas1cube3d.hh000066400000000000000000000041421411343327200307140ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ RT1Cube3DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::hexahedron; } private: RT1Cube3DLocalBasis basis; RT1Cube3DLocalCoefficients coefficients; RT1Cube3DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas1cube3d/000077500000000000000000000000001411343327200303725ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas1cube3d/CMakeLists.txt000066400000000000000000000003531411343327200331330ustar00rootroot00000000000000install(FILES raviartthomas1cube3dlocalbasis.hh raviartthomas1cube3dlocalcoefficients.hh raviartthomas1cube3dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas1cube3d) raviartthomas1cube3dlocalbasis.hh000066400000000000000000000602701411343327200367310ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ RT1Cube3DLocalBasis (unsigned int s = 0) { 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.hh000066400000000000000000000024371411343327200402720ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000136371411343327200405240ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 Make set number s, where 0 <= s < 64 * * \param s Edge orientation indicator */ RT1Cube3DLocalInterpolation (std::bitset<6> s = 0) { for (size_t i=0; i<6; i++) sign_[i] = (s[i]) ? -1.0 : 1.0; n_[0] = {-1.0, 0.0, 0.0}; n_[1] = { 1.0, 0.0, 0.0}; n_[2] = { 0.0, -1.0, 0.0}; n_[3] = { 0.0, 1.0, 0.0}; n_[4] = { 0.0, 0.0, -1.0}; n_[5] = { 0.0, 0.0, 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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(36); fill(out.begin(), out.end(), 0.0); const int qOrder = 3; const auto& rule1 = QuadratureRules::rule(GeometryTypes::cube(2), qOrder); for (auto&& qp : rule1) { Dune::FieldVector qPos = qp.position(); typename LB::Traits::DomainType localPos; localPos = {0.0, qPos[0], qPos[1]}; auto y = f(localPos); out[0] += (y[0]*n_[0][0] + y[1]*n_[0][1] + y[2]*n_[0][2])*qp.weight()*sign_[0]; out[6] += (y[0]*n_[0][0] + y[1]*n_[0][1] + y[2]*n_[0][2])*(2.0*qPos[0] - 1.0)*qp.weight(); out[12] += (y[0]*n_[0][0] + y[1]*n_[0][1] + y[2]*n_[0][2])*(2.0*qPos[1] - 1.0)*qp.weight(); out[18] += (y[0]*n_[0][0] + y[1]*n_[0][1] + y[2]*n_[0][2])*(2.0*qPos[0] - 1.0)*(2.0*qPos[1] - 1.0)*qp.weight(); localPos = {1.0, qPos[0], qPos[1]}; y = f(localPos); out[1] += (y[0]*n_[1][0] + y[1]*n_[1][1] + y[2]*n_[1][2])*qp.weight()*sign_[1]; out[7] += (y[0]*n_[1][0] + y[1]*n_[1][1] + y[2]*n_[1][2])*(1.0 - 2.0*qPos[0])*qp.weight(); out[13] += (y[0]*n_[1][0] + y[1]*n_[1][1] + y[2]*n_[1][2])*(1.0 - 2.0*qPos[1])*qp.weight(); out[19] += (y[0]*n_[1][0] + y[1]*n_[1][1] + y[2]*n_[1][2])*(1.0 - 2.0*qPos[0])*(2.0*qPos[1] - 1.0)*qp.weight(); localPos = {qPos[0], 0.0, qPos[1]}; y = f(localPos); out[2] += (y[0]*n_[2][0] + y[1]*n_[2][1] + y[2]*n_[2][2])*qp.weight()*sign_[2]; out[8] += (y[0]*n_[2][0] + y[1]*n_[2][1] + y[2]*n_[2][2])*(1.0 - 2.0*qPos[0])*qp.weight(); out[14] += (y[0]*n_[2][0] + y[1]*n_[2][1] + y[2]*n_[2][2])*(2.0*qPos[1] - 1.0)*qp.weight(); out[20] += (y[0]*n_[2][0] + y[1]*n_[2][1] + y[2]*n_[2][2])*(1.0 - 2.0*qPos[0])*(2.0*qPos[1] - 1.0)*qp.weight(); localPos = {qPos[0], 1.0, qPos[1]}; y = f(localPos); out[3] += (y[0]*n_[3][0] + y[1]*n_[3][1] + y[2]*n_[3][2])*qp.weight()*sign_[3]; out[9] += (y[0]*n_[3][0] + y[1]*n_[3][1] + y[2]*n_[3][2])*(2.0*qPos[0] - 1.0)*qp.weight(); out[15] += (y[0]*n_[3][0] + y[1]*n_[3][1] + y[2]*n_[3][2])*(1.0 - 2.0*qPos[1])*qp.weight(); out[21] += (y[0]*n_[3][0] + y[1]*n_[3][1] + y[2]*n_[3][2])*(2.0*qPos[0] - 1.0)*(2.0*qPos[1] - 1.0)*qp.weight(); localPos = {qPos[0], qPos[1], 0.0}; y = f(localPos); out[4] += (y[0]*n_[4][0] + y[1]*n_[4][1] + y[2]*n_[4][2])*qp.weight()*sign_[4]; out[10] += (y[0]*n_[4][0] + y[1]*n_[4][1] + y[2]*n_[4][2])*(1.0 - 2.0*qPos[0])*qp.weight(); out[16] += (y[0]*n_[4][0] + y[1]*n_[4][1] + y[2]*n_[4][2])*(1.0 - 2.0*qPos[1])*qp.weight(); out[22] += (y[0]*n_[4][0] + y[1]*n_[4][1] + y[2]*n_[4][2])*(1.0 - 2.0*qPos[0])*(2.0*qPos[1] - 1.0)*qp.weight(); localPos = {qPos[0], qPos[1], 1.0}; y = f(localPos); out[5] += (y[0]*n_[5][0] + y[1]*n_[5][1] + y[2]*n_[5][2])*qp.weight()*sign_[5]; out[11] += (y[0]*n_[5][0] + y[1]*n_[5][1] + y[2]*n_[5][2])*(2.0*qPos[0] - 1.0)*qp.weight(); out[17] += (y[0]*n_[5][0] + y[1]*n_[5][1] + y[2]*n_[5][2])*(2.0*qPos[1] - 1.0)*qp.weight(); out[23] += (y[0]*n_[5][0] + y[1]*n_[5][1] + y[2]*n_[5][2])*(2.0*qPos[0] - 1.0)*(2.0*qPos[1] - 1.0)*qp.weight(); } const auto& rule2 = QuadratureRules::rule(GeometryTypes::cube(3), qOrder); for (auto&& qp : rule2) { FieldVector qPos = qp.position(); auto y = f(qPos); out[24] += y[0]*qp.weight(); out[25] += y[1]*qp.weight(); out[26] += y[2]*qp.weight(); out[27] += y[0]*qPos[1]*qp.weight(); out[28] += y[0]*qPos[2]*qp.weight(); out[29] += y[1]*qPos[0]*qp.weight(); out[30] += y[1]*qPos[2]*qp.weight(); out[31] += y[2]*qPos[0]*qp.weight(); out[32] += y[2]*qPos[1]*qp.weight(); out[33] += y[0]*qPos[1]*qPos[2]*qp.weight(); out[34] += y[1]*qPos[0]*qPos[2]*qp.weight(); out[35] += y[2]*qPos[0]*qPos[1]*qp.weight(); } } private: // Facet orientations std::array sign_; // Facet normals std::array n_; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS1_CUBE3D_LOCALINTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas2cube2d.hh000066400000000000000000000041461411343327200307200ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT2Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::quadrilateral; } private: RT2Cube2DLocalBasis basis; RT2Cube2DLocalCoefficients coefficients; RT2Cube2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas2cube2d/000077500000000000000000000000001411343327200303725ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas2cube2d/CMakeLists.txt000066400000000000000000000003531411343327200331330ustar00rootroot00000000000000install(FILES raviartthomas2cube2dlocalbasis.hh raviartthomas2cube2dlocalcoefficients.hh raviartthomas2cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas2cube2d) raviartthomas2cube2dlocalbasis.hh000066400000000000000000000415201411343327200367260ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT2Cube2DLocalBasis (unsigned int s = 0) { 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.hh000066400000000000000000000023671411343327200402740ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000104421411343327200405130ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT2Cube2DLocalInterpolation (std::bitset<4> s = 0) { for (size_t i=0; i<4; i++) sign_[i] = (s[i]) ? -1.0 : 1.0; n_[0] = {-1.0, 0.0}; n_[1] = { 1.0, 0.0}; n_[2] = { 0.0, -1.0}; n_[3] = { 0.0, 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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(24); fill(out.begin(), out.end(), 0.0); const int qOrder = 6; const auto& rule1 = QuadratureRules::rule(GeometryTypes::cube(1), qOrder); for (auto&& qp : rule1) { Scalar qPos = qp.position(); typename LB::Traits::DomainType localPos; localPos = {0.0, qPos}; auto y = f(localPos); out[0] += (y[0]*n_[0][0] + y[1]*n_[0][1])*qp.weight()*sign_[0]; out[1] += (y[0]*n_[0][0] + y[1]*n_[0][1])*(2.0*qPos - 1.0)*qp.weight(); out[2] += (y[0]*n_[0][0] + y[1]*n_[0][1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*qp.weight()*sign_[0]; localPos = {1.0, qPos}; y = f(localPos); out[3] += (y[0]*n_[1][0] + y[1]*n_[1][1])*qp.weight()*sign_[1]; out[4] += (y[0]*n_[1][0] + y[1]*n_[1][1])*(1.0 - 2.0*qPos)*qp.weight(); out[5] += (y[0]*n_[1][0] + y[1]*n_[1][1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*qp.weight()*sign_[1]; localPos = {qPos, 0.0}; y = f(localPos); out[6] += (y[0]*n_[2][0] + y[1]*n_[2][1])*qp.weight()*sign_[2]; out[7] += (y[0]*n_[2][0] + y[1]*n_[2][1])*(1.0 - 2.0*qPos)*qp.weight(); out[8] += (y[0]*n_[2][0] + y[1]*n_[2][1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*qp.weight()*sign_[2]; localPos = {qPos, 1.0}; y = f(localPos); out[9] += (y[0]*n_[3][0] + y[1]*n_[3][1])*qp.weight()*sign_[3]; out[10] += (y[0]*n_[3][0] + y[1]*n_[3][1])*(2.0*qPos - 1.0)*qp.weight(); out[11] += (y[0]*n_[3][0] + y[1]*n_[3][1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*qp.weight()*sign_[3]; } const auto& rule2 = QuadratureRules::rule(GeometryTypes::cube(2), qOrder); for (auto&& qp : rule2) { FieldVector qPos = qp.position(); auto y = f(qPos); out[12] += y[0]*qp.weight(); out[13] += y[1]*qp.weight(); out[14] += y[0]*qPos[0]*qp.weight(); out[15] += y[1]*qPos[0]*qp.weight(); out[16] += y[0]*qPos[1]*qp.weight(); out[17] += y[1]*qPos[1]*qp.weight(); out[18] += y[0]*qPos[0]*qPos[1]*qp.weight(); out[19] += y[1]*qPos[0]*qPos[1]*qp.weight(); out[20] += y[0]*qPos[1]*qPos[1]*qp.weight(); out[21] += y[1]*qPos[0]*qPos[0]*qp.weight(); out[22] += y[0]*qPos[0]*qPos[1]*qPos[1]*qp.weight(); out[23] += y[1]*qPos[0]*qPos[0]*qPos[1]*qp.weight(); } } private: // Edge orientations std::array sign_; // Edge normals std::array n_; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS2_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas3cube2d.hh000066400000000000000000000042271411343327200307210ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT3Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::quadrilateral; } private: RT3Cube2DLocalBasis basis; RT3Cube2DLocalCoefficients coefficients; RT3Cube2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas3cube2d/000077500000000000000000000000001411343327200303735ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas3cube2d/CMakeLists.txt000066400000000000000000000003531411343327200331340ustar00rootroot00000000000000install(FILES raviartthomas3cube2dlocalbasis.hh raviartthomas3cube2dlocalcoefficients.hh raviartthomas3cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas3cube2d) raviartthomas3cube2dlocalbasis.hh000066400000000000000000000467461411343327200367470ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT3Cube2DLocalBasis (std::bitset<4> s = 0) { 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.hh000066400000000000000000000024371411343327200402740ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000133051411343327200405160ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT3Cube2DLocalInterpolation (std::bitset<4> s = 0) { for (size_t i=0; i<4; i++) sign_[i] = (s[i]) ? -1.0 : 1.0; n_[0] = {-1.0, 0.0}; n_[1] = { 1.0, 0.0}; n_[2] = { 0.0, -1.0}; n_[3] = { 0.0, 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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(40); fill(out.begin(), out.end(), 0.0); const int qOrder = 9; const auto& rule1 = QuadratureRules::rule(GeometryTypes::cube(1), qOrder); for (auto&& qp : rule1) { Scalar qPos = qp.position(); typename LB::Traits::DomainType localPos; localPos = {0.0, qPos}; auto y = f(localPos); out[0] += (y[0]*n_[0][0] + y[1]*n_[0][1])*qp.weight()*sign_[0]; out[1] += (y[0]*n_[0][0] + y[1]*n_[0][1])*(2.0*qPos - 1.0)*qp.weight(); out[2] += (y[0]*n_[0][0] + y[1]*n_[0][1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*qp.weight()*sign_[0]; out[3] += (y[0]*n_[0][0] + y[1]*n_[0][1])*(20.0*qPos*qPos*qPos - 30.0*qPos*qPos + 12.0*qPos - 1.0)*qp.weight(); localPos = {1.0, qPos}; y = f(localPos); out[4] += (y[0]*n_[1][0] + y[1]*n_[1][1])*qp.weight()*sign_[1]; out[5] += (y[0]*n_[1][0] + y[1]*n_[1][1])*(1.0 - 2.0*qPos)*qp.weight(); out[6] += (y[0]*n_[1][0] + y[1]*n_[1][1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*qp.weight()*sign_[1]; out[7] += (y[0]*n_[1][0] + y[1]*n_[1][1])*(-20.0*qPos*qPos*qPos + 30.0*qPos*qPos - 12.0*qPos + 1.0)*qp.weight(); localPos = {qPos, 0.0}; y = f(localPos); out[8] += (y[0]*n_[2][0] + y[1]*n_[2][1])*qp.weight()*sign_[2]; out[9] += (y[0]*n_[2][0] + y[1]*n_[2][1])*(1.0 - 2.0*qPos)*qp.weight(); out[10] += (y[0]*n_[2][0] + y[1]*n_[2][1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*qp.weight()*sign_[2]; out[11] += (y[0]*n_[2][0] + y[1]*n_[2][1])*(-20.0*qPos*qPos*qPos + 30.0*qPos*qPos - 12.0*qPos + 1.0)*qp.weight(); localPos = {qPos, 1.0}; y = f(localPos); out[12] += (y[0]*n_[3][0] + y[1]*n_[3][1])*qp.weight()*sign_[3]; out[13] += (y[0]*n_[3][0] + y[1]*n_[3][1])*(2.0*qPos - 1.0)*qp.weight(); out[14] += (y[0]*n_[3][0] + y[1]*n_[3][1])*(6.0*qPos*qPos - 6.0*qPos + 1.0)*qp.weight()*sign_[3]; out[15] += (y[0]*n_[3][0] + y[1]*n_[3][1])*(20.0*qPos*qPos*qPos - 30.0*qPos*qPos + 12.0*qPos - 1.0)*qp.weight(); } const auto& rule2 = QuadratureRules::rule(GeometryTypes::cube(2), qOrder); for (auto&& qp : rule2) { auto qPos = qp.position(); auto y = f(qPos); 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*qp.weight(); out[17] += y[0]*l0_x*l1_y*qp.weight(); out[18] += y[0]*l0_x*l2_y*qp.weight(); out[19] += y[0]*l0_x*l3_y*qp.weight(); out[20] += y[0]*l1_x*l0_y*qp.weight(); out[21] += y[0]*l1_x*l1_y*qp.weight(); out[22] += y[0]*l1_x*l2_y*qp.weight(); out[23] += y[0]*l1_x*l3_y*qp.weight(); out[24] += y[0]*l2_x*l0_y*qp.weight(); out[25] += y[0]*l2_x*l1_y*qp.weight(); out[26] += y[0]*l2_x*l2_y*qp.weight(); out[27] += y[0]*l2_x*l3_y*qp.weight(); out[28] += y[1]*l0_x*l0_y*qp.weight(); out[29] += y[1]*l0_x*l1_y*qp.weight(); out[30] += y[1]*l0_x*l2_y*qp.weight(); out[31] += y[1]*l1_x*l0_y*qp.weight(); out[32] += y[1]*l1_x*l1_y*qp.weight(); out[33] += y[1]*l1_x*l2_y*qp.weight(); out[34] += y[1]*l2_x*l0_y*qp.weight(); out[35] += y[1]*l2_x*l1_y*qp.weight(); out[36] += y[1]*l2_x*l2_y*qp.weight(); out[37] += y[1]*l3_x*l0_y*qp.weight(); out[38] += y[1]*l3_x*l1_y*qp.weight(); out[39] += y[1]*l3_x*l2_y*qp.weight(); } } private: // Edge orientations std::array sign_; // Edge normals std::array n_; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS3_CUBE2D_LOCALINTERPOLATION_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas4cube2d.hh000066400000000000000000000042271411343327200307220ustar00rootroot00000000000000// -*- 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 () {} /** * \brief Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT4Cube2DLocalFiniteElement (int s) : basis(s), interpolation(s) {} 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(); } static constexpr GeometryType type () { return GeometryTypes::quadrilateral; } private: RT4Cube2DLocalBasis basis; RT4Cube2DLocalCoefficients coefficients; RT4Cube2DLocalInterpolation > interpolation; }; } #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS4_CUBE2D_LOCALFINITEELEMENT_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas4cube2d/000077500000000000000000000000001411343327200303745ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomas4cube2d/CMakeLists.txt000066400000000000000000000003531411343327200331350ustar00rootroot00000000000000install(FILES raviartthomas4cube2dlocalbasis.hh raviartthomas4cube2dlocalcoefficients.hh raviartthomas4cube2dlocalinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomas4cube2d) raviartthomas4cube2dlocalbasis.hh000066400000000000000000000664641411343327200367500ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT4Cube2DLocalBasis (std::bitset<4> s = 0) { 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.hh000066400000000000000000000025051411343327200402720ustar00rootroot00000000000000dune-localfunctions-2.8.0/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.hh000066400000000000000000000137311411343327200405230ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 #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 Make set number s, where 0 <= s < 16 * * \param s Edge orientation indicator */ RT4Cube2DLocalInterpolation (unsigned int s = 0) { 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 ff function which should be interpolated * \param out return value, vector of coefficients */ template void interpolate (const F& ff, 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; auto&& f = Impl::makeFunctionWithCallOperator(ff); out.resize(60); fill(out.begin(), out.end(), 0.0); const int qOrder = 12; const QuadratureRule& rule = QuadratureRules::rule(GeometryTypes::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; auto y = f(localPos); 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; y = f(localPos); 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; y = f(localPos); 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; y = f(localPos); 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(GeometryTypes::cube(2), qOrder); for (typename QuadratureRule::const_iterator it = rule2.begin(); it != rule2.end(); ++it) { FieldVector qPos = it->position(); auto y = f(qPos); 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.8.0/dune/localfunctions/raviartthomas/raviartthomascube.hh000066400000000000000000000114461411343327200304110ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/raviartthomas/raviartthomaslfecache.hh000066400000000000000000000071351411343327200312250ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASLFECACHE_HH #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASLFECACHE_HH #include #include #include #include #include #include namespace Dune { namespace Impl { // Provide implemented Raviart-Thomas local finite elements template struct ImplementedRaviartThomasLocalFiniteElements {}; template struct ImplementedRaviartThomasLocalFiniteElements : public FixedDimLocalGeometryTypeIndex<2> { using FixedDimLocalGeometryTypeIndex<2>::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::triangle), []() { return RT02DLocalFiniteElement(); }), std::make_pair(index(GeometryTypes::quadrilateral), []() { return RT0Cube2DLocalFiniteElement(); }) ); } }; template struct ImplementedRaviartThomasLocalFiniteElements : public FixedDimLocalGeometryTypeIndex<2> { using FixedDimLocalGeometryTypeIndex<2>::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::triangle), []() { return RT12DLocalFiniteElement(); }), std::make_pair(index(GeometryTypes::quadrilateral), []() { return RT1Cube2DLocalFiniteElement(); }) ); } }; template struct ImplementedRaviartThomasLocalFiniteElements : public FixedDimLocalGeometryTypeIndex<2> { using FixedDimLocalGeometryTypeIndex<2>::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::quadrilateral), []() { return RT2Cube2DLocalFiniteElement(); }) ); } }; template struct ImplementedRaviartThomasLocalFiniteElements : public FixedDimLocalGeometryTypeIndex<3> { using FixedDimLocalGeometryTypeIndex<3>::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::tetrahedron), []() { return RT03DLocalFiniteElement(); }), std::make_pair(index(GeometryTypes::hexahedron), []() { return RT0Cube3DLocalFiniteElement(); }) ); } }; template struct ImplementedRaviartThomasLocalFiniteElements : public FixedDimLocalGeometryTypeIndex<3> { using FixedDimLocalGeometryTypeIndex<3>::index; static auto getImplementations() { return std::make_tuple( std::make_pair(index(GeometryTypes::hexahedron), []() { RT1Cube3DLocalFiniteElement(); }) ); } }; } // namespace Impl /** \brief A cache that stores all available Raviart-Thomas local finite elements for the given dimension and order * * \tparam D Type used for domain coordinates * \tparam R Type used for shape function values * \tparam dim Element dimension * \tparam order Element order * * The cached finite element implementations can be obtained using get(GeometryType). */ template using RaviartThomasLocalFiniteElementCache = LocalFiniteElementVariantCache>; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASLFECACHE_HH dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomassimplex.hh000066400000000000000000000035041411343327200311500ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/raviartthomas/raviartthomassimplex/000077500000000000000000000000001411343327200306255ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/raviartthomas/raviartthomassimplex/CMakeLists.txt000066400000000000000000000003301411343327200333610ustar00rootroot00000000000000install(FILES raviartthomassimplexbasis.hh raviartthomassimplexinterpolation.hh raviartthomassimplexprebasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/raviartthomas/raviartthomassimplex) raviartthomassimplexbasis.hh000066400000000000000000000027431411343327200364050ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 { /* * `RTPreBasisFactory` provides a basis for the Raviart-Thomas function space. * `RaviartThomasL2InterpolationFactory` provides the linear functionals. * * `Defaultbasisfactory::create` first builds the function space and the linear functionals. * Then the constructor of `BasisMatrix` gets called. There the matrix * * \begin{equation} * A_{i,j} := N_j(\phi_i) * \end{equation} * * with linear functionals $N_j$ and basisfunctions $\phi_i$ gets assembled. * Then the matrix gets inverted and is then used as a coefficent matrix for the standard monomial basis. * * For more details on the theory see the first chapter "Construction of Local Finite Element Spaces Using the Generic Reference Elements" * of the book "Advances in Dune" by Dedner, Flemisch and Klöfkorn published in 2012. */ template< unsigned int dim, class SF, class CF > struct RaviartThomasBasisFactory : public DefaultBasisFactory< RTPreBasisFactory, RaviartThomasL2InterpolationFactory, dim,dim,SF,CF > {}; } #endif // #ifndef DUNE_RAVIARTTHOMASBASIS_HH raviartthomassimplexinterpolation.hh000066400000000000000000000351431411343327200401730ustar00rootroot00000000000000dune-localfunctions-2.8.0/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, 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 ]; } std::size_t size () const { return localKey_.size(); } private: std::vector< LocalKey > localKey_; }; // RaviartThomasCoefficientsFactory // -------------------------------- template < unsigned int dim > struct RaviartThomasCoefficientsFactory { typedef std::size_t Key; typedef const LocalCoefficientsContainer Object; template< GeometryType::Id geometryId > static Object *create( const Key &key ) { typedef RaviartThomasL2InterpolationFactory< dim, double > InterpolationFactory; if( !supports< geometryId >( key ) ) return nullptr; typename InterpolationFactory::Object *interpolation = InterpolationFactory::template create< geometryId >( key ); Object *localKeys = new Object( *interpolation ); InterpolationFactory::release( interpolation ); return localKeys; } template< GeometryType::Id geometryId > static bool supports ( const Key &key ) { return GeometryType(geometryId).isSimplex(); } static void release( Object *object ) { delete object; } }; // 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; // for the dofs associated to the element typedef OrthonormalBasisFactory< dimension, Field > TestBasisFactory; typedef typename TestBasisFactory::Object TestBasis; // for the dofs associated to the faces typedef OrthonormalBasisFactory< dimension-1, Field > TestFaceBasisFactory; typedef typename TestFaceBasisFactory::Object TestFaceBasis; // the normals of the faces 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_ ); } [[deprecated("Use type().id() instead.")]] unsigned int topologyId () const { return type().id(); } GeometryType type () const { return geometry_; } std::size_t order () const { return order_; } // number of faces unsigned int faceSize () const { return faceSize_; } // basis associated to the element TestBasis *testBasis () const { return testBasis_; } // basis associated to face f TestFaceBasis *testFaceBasis ( unsigned int f ) const { assert( f < faceSize() ); return faceStructure_[ f ].basis_; } // normal of face f const Normal &normal ( unsigned int f ) const { assert( f < faceSize() ); return *(faceStructure_[ f ].normal_); } template< GeometryType::Id geometryId > void build ( std::size_t order ) { constexpr GeometryType geometry = geometryId; geometry_ = geometry; order_ = order; testBasis_ = (order > 0 ? TestBasisFactory::template create< geometry >( 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 ) { /* For simplices or cubes of arbitrary dimension you could just use * * ``` * GeometryType faceGeometry = Impl::getBase(geometry_); * TestFaceBasis *faceBasis = TestFaceBasisFactory::template create< faceGeometry >( order ); * ``` * * For i.e. Prisms and Pyramids in 3d this does not work because they contain squares and triangles as faces. * And depending on the dynamic face index a different face geometry is needed. * */ TestFaceBasis *faceBasis = Impl::toGeometryTypeIdConstant(refElement.type( face, 1 ), [&](auto faceGeometryTypeId) { return TestFaceBasisFactory::template create< decltype(faceGeometryTypeId)::value >( 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_; }; std::vector< FaceStructure > faceStructure_; TestBasis *testBasis_ = nullptr; GeometryType geometry_; unsigned int faceSize_; std::size_t order_; }; // 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 Vector > auto interpolate ( const Function &function, Vector &coefficients ) const -> std::enable_if_t< std::is_same< decltype(std::declval().resize(1) ),void >::value,void> { coefficients.resize(size()); typename Base::template Helper func( function,coefficients ); interpolate(func); } template< class Basis, class Matrix > auto interpolate ( const Basis &basis, Matrix &matrix ) const -> std::enable_if_t< std::is_same< decltype(std::declval().rowPtr(0)), typename Matrix::Field* >::value,void> { matrix.resize( size(), basis.size() ); typename Base::template Helper func( basis,matrix ); interpolate(func); } std::size_t order() const { return order_; } std::size_t size() const { return size_; } template void build( std::size_t 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_.type(); std::vector< Field > testBasisVal; for (unsigned int i=0; i FaceQuadrature; typedef Dune::QuadratureRules FaceQuadratureRules; const auto &refElement = Dune::ReferenceElements< Field, dimension >::general( geoType ); for (unsigned int f=0; fsize()); const auto &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 * * \param startRow row of matrix to start * \param mVal value of the testBasis at a quadrature point on a face * \param rtVal value of the RaviartThomasBasis at a quadrature point on a face * \param normal the normal of the face * \param weight quadrature weight * \param matrix result gets written into matrix starting with row: row */ 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() ); } } /** \brief evaluate interior functionals * * \param startRow row of matrix to start * \param mVal value of the testBasis at a quadrature point in the interior of the ReferenceElement * \param rtVal value of the RaviartThomasBasis at a quadrature point in the interior of the ReferenceElement * \param weight quadrature weight * \param matrix result gets written into matrix starting with row: row */ 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 RaviartThomasL2InterpolationFactory { typedef RTL2InterpolationBuilder Builder; typedef const RaviartThomasL2Interpolation Object; typedef std::size_t Key; typedef typename std::remove_const::type NonConstObject; template static Object *create( const Key &key ) { if ( !supports(key) ) return 0; NonConstObject *interpol = new NonConstObject(); interpol->template build(key); return interpol; } template< GeometryType::Id geometryId > static bool supports ( const Key &key ) { return GeometryType(geometryId).isSimplex(); } static void release( Object *object ) { delete object; } }; } // namespace Dune #endif // #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASSIMPLEX_RAVIARTTHOMASSIMPLEXINTERPOLATION_HH raviartthomassimplexprebasis.hh000066400000000000000000000136341411343327200371150ustar00rootroot00000000000000dune-localfunctions-2.8.0/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 < GeometryType::Id geometryId, class Field > struct RTVecMatrix; template struct RTPreBasisFactory { typedef MonomialBasisProvider MBasisFactory; typedef typename MBasisFactory::Object MBasis; typedef StandardEvaluator EvalMBasis; typedef PolynomialBasisWithMatrix > Basis; typedef const Basis Object; typedef std::size_t Key; template struct EvaluationBasisFactory { typedef MonomialBasisProvider Type; }; template< GeometryType::Id geometryId > static Object *create ( const Key &order ) { RTVecMatrix vecMatrix(order); MBasis *mbasis = MBasisFactory::template create(order+1); typename std::remove_const::type *tmBasis = new typename std::remove_const::type(*mbasis); tmBasis->fill(vecMatrix); return tmBasis; } static void release( Object *object ) { delete object; } }; template struct RTVecMatrix { static constexpr GeometryType geometry = geometryId; static const unsigned int dim = geometry.dim(); typedef MultiIndex MI; typedef MonomialBasis MIBasis; RTVecMatrix(std::size_t order) { /* * Construction of Raviart-Thomas elements in high dimensions see "Mixed Finite Elements in \R^3" by Nedelec, 1980. * * Let $\P_{n,k}$ be the space of polynomials in $n$ variables with degree $\leq k$. * The space of Raviart-Thomas functions in $n$ dimensions with index $k$ is defined as * * \begin{equation*} * RT_k := (\P_{k-1})^n \oplus \widetilde \P_k x * \end{equation*} * with $x=(x_1,x_2,\dots, x_n)$ in $n$ dimensions and $\widetilde \P_k$ the homogeneous polynomials of degree $k$. * * For $RT_k$ holds * \begin{equation*} * (\P_{k-1})^n \subset RT_k \subset (\P_k)^n. * \end{equation*} * * We construct $(\P_k)^n$ and and only use the monomials contained in $RT_k$. * */ MIBasis basis(order+1); FieldVector< MI, dim > x; /* * Init MultiIndices * x[0]=(1,0,0) x * x[1]=(0,1,0) y * x[2]=(0,0,1) z */ for( unsigned int i = 0; i < dim; ++i ) x[ i ].set( i, 1 ); std::vector< MI > val( basis.size() ); // val now contains all monomials in $n$ dimensions with degree $\leq order+1$ basis.evaluate( x, val ); col_ = basis.size(); // get $\dim (\P_{order-1})$ unsigned int notHomogen = 0; if (order>0) notHomogen = basis.sizes()[order-1]; // get $\dim \widetilde (\P_order)$ unsigned int homogen = basis.sizes()[order]-notHomogen; /* * * The set $RT_k$ is defined as * * \begin{equation} * RT_k := (\P_k)^dim + \widetilde \P_k x with x\in \R^n. * \end{equation} * * The space $\P_k$ is split in $\P_k = \P_{k-1} + \widetilde \P_k$. * * \begin{align} * RT_k &= (\P_{k-1} + \widetilde \P_k)^dim + \widetilde \P_k x with x\in \R^n * &= (\P_{k-1})^n + (\widetilde \P_k)^n + \widetilde \P_k x with x\in \R^n * \end{align} * * Thus $\dim RT_k = n * \dim \P_{k-1} + (n+1)*\dim (\widetilde \P_k)$ */ // row_ = \dim RT_k *dim row_ = (notHomogen*dim+homogen*(dim+1))*dim; mat_ = new Field*[row_]; int row = 0; /* Assign the correct values for the nonhomogeneous polymonials $p\in (\P_{oder-1})^dim$ * A basis function is represented by $dim$ rows. */ 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.8.0/dune/localfunctions/refined/000077500000000000000000000000001411343327200230675ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/refined/CMakeLists.txt000066400000000000000000000003051411343327200256250ustar00rootroot00000000000000add_subdirectory(common) add_subdirectory(refinedp0) add_subdirectory(refinedp1) install(FILES refinedp0.hh refinedp1.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/refined) dune-localfunctions-2.8.0/dune/localfunctions/refined/common/000077500000000000000000000000001411343327200243575ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/refined/common/CMakeLists.txt000066400000000000000000000001701411343327200271150ustar00rootroot00000000000000install(FILES refinedsimplexlocalbasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/refined/common) dune-localfunctions-2.8.0/dune/localfunctions/refined/common/refinedsimplexlocalbasis.hh000066400000000000000000000245201411343327200317560ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/refined/refinedp0.hh000066400000000000000000000121331411343327200252640ustar00rootroot00000000000000// -*- 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 () {} /** \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 ! */ static constexpr GeometryType type () { return GeometryTypes::line; } private: RefinedP0LocalBasis basis_; RefinedP0LocalCoefficients<1> coefficients_; RefinedP0LocalInterpolation > interpolation_; }; /** \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 () {} /** \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 ! */ static constexpr GeometryType type () { return GeometryTypes::triangle; } private: RefinedP0LocalBasis basis_; RefinedP0LocalCoefficients<2> coefficients_; RefinedP0LocalInterpolation > interpolation_; }; /** \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 () {} /** \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 ! */ static constexpr GeometryType type () { return GeometryTypes::tetrahedron; } private: RefinedP0LocalBasis basis_; RefinedP0LocalCoefficients<3> coefficients_; RefinedP0LocalInterpolation > interpolation_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/refined/refinedp0/000077500000000000000000000000001411343327200247435ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/refined/refinedp0/CMakeLists.txt000066400000000000000000000002711411343327200275030ustar00rootroot00000000000000install(FILES refinedp0localbasis.hh refinedp0localcoefficients.hh refinedp0localinterpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/refined/refinedp0) dune-localfunctions-2.8.0/dune/localfunctions/refined/refinedp0/refinedp0localbasis.hh000066400000000000000000000056621411343327200312060ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/refined/refinedp0/refinedp0localcoefficients.hh000066400000000000000000000020601411343327200325330ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/refined/refinedp0/refinedp0localinterpolation.hh000066400000000000000000000077551411343327200330010ustar00rootroot00000000000000// -*- 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 #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& ff, std::vector& out) const { auto&& f = Impl::makeFunctionWithCallOperator
(ff); out.resize(interpolationPoints_.size()); for (size_t i = 0; i < out.size(); ++i) { out[i] = f(interpolationPoints_[i]); } } 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& ff, std::vector& out) const { auto&& f = Impl::makeFunctionWithCallOperator
(ff); out.resize(interpolationPoints_.size()); for (size_t i = 0; i < out.size(); ++i) { out[i] = f(interpolationPoints_[i]); } } 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& ff, std::vector& out) const { auto&& f = Impl::makeFunctionWithCallOperator
(ff); out.resize(interpolationPoints_.size()); for (size_t i = 0; i < out.size(); ++i) { out[i] = f(interpolationPoints_[i]); } } private: std::vector
interpolationPoints_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/refined/refinedp1.hh000066400000000000000000000053611411343327200252720ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_LOCALFUNCTIONS_REFINED_REFINEDP1_HH #define DUNE_LOCALFUNCTIONS_REFINED_REFINEDP1_HH #include #include #include #include #include namespace Dune { /** \brief Piecewise linear continuous Lagrange functions on a uniformly refined simplex element * * \tparam D Number type used for domain coordinates * \tparam R Number type used for shape function values * \tparam dim Dimension of the domain */ template class RefinedP1LocalFiniteElement { public: /** \brief Export all types used by this implementation */ typedef LocalFiniteElementTraits, Impl::LagrangeSimplexLocalCoefficients, Impl::LagrangeSimplexLocalInterpolation > > Traits; /** \brief Default constructor */ RefinedP1LocalFiniteElement () {} /** \brief The set of shape functions */ const typename Traits::LocalBasisType& localBasis () const { return basis_; } /** \brief Produces the assignments of the degrees of freedom to the element subentities */ const typename Traits::LocalCoefficientsType& localCoefficients () const { return coefficients_; } /** \brief Evaluates all degrees of freedom for a given function */ const typename Traits::LocalInterpolationType& localInterpolation () const { return interpolation_; } /** \brief Number of shape functions of this finite element */ unsigned int size () const { return basis_.size(); } /** \brief The element type that this finite element is defined on */ static constexpr GeometryType type () { return GeometryTypes::simplex(dim); } private: RefinedP1LocalBasis basis_; Impl::LagrangeSimplexLocalCoefficients coefficients_; // Yes, the template argument here really is LagrangeSimplexLocalBasis, even though this is not // the local basis of the refined locale finite element: The reason is that LagrangeSimplexLocalInterpolation // uses this argument to determine the polynomial order, and RefinedP1LocalBasis returns order 1 // whereas order 2 is needed here. Impl::LagrangeSimplexLocalInterpolation > interpolation_; }; } #endif // DUNE_LOCALFUNCTIONS_REFINED_REFINEDP1_HH dune-localfunctions-2.8.0/dune/localfunctions/refined/refinedp1/000077500000000000000000000000001411343327200247445ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/refined/refinedp1/CMakeLists.txt000066400000000000000000000001661411343327200275070ustar00rootroot00000000000000install(FILES refinedp1localbasis.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/refined/refinedp1) dune-localfunctions-2.8.0/dune/localfunctions/refined/refinedp1/refinedp1localbasis.hh000066400000000000000000000577521411343327200312170ustar00rootroot00000000000000// -*- 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. 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 ~ (0.5) f_2 ~ (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 static constexpr unsigned int size () { 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 */ static constexpr unsigned int order () { 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 static constexpr unsigned int size () { 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 */ static constexpr unsigned int order () { 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 static constexpr unsigned int size () { 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 */ static constexpr unsigned int order () { return 1; } }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/test/000077500000000000000000000000001411343327200224325ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/test/CMakeLists.txt000066400000000000000000000055151411343327200252000ustar00rootroot00000000000000add_definitions(-DDUNE_DEPRECATED_INTERPOLATE_CHECK=1) dune_add_test(SOURCES bdfmelementtest.cc) dune_add_test(SOURCES brezzidouglasmarinielementtest.cc) dune_add_test(SOURCES crouzeixraviartelementtest.cc) dune_add_test(SOURCES dualmortarelementtest.cc) dune_add_test(SOURCES hierarchicalelementtest.cc) dune_add_test(SOURCES testgenericfem.cc) dune_add_test(SOURCES lagrangeshapefunctiontest.cc) dune_add_test(SOURCES monomialshapefunctiontest.cc) dune_add_test(SOURCES nedelec1stkindelementtest.cc) dune_add_test(SOURCES rannacherturekelementtest.cc) dune_add_test(SOURCES raviartthomaselementtest.cc) dune_add_test(SOURCES refinedelementtest.cc) dune_add_test(SOURCES virtualshapefunctiontest.cc) dune_add_test(SOURCES test-edges0.5.cc) dune_add_test(SOURCES test-finiteelementcache.cc) dune_add_test(SOURCES globalmonomialfunctionstest.cc) 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 "CHECKDIM=1") dune_add_test(NAME test-lagrange2 SOURCES test-lagrange.cc COMPILE_DEFINITIONS "CHECKDIM=2") dune_add_test(NAME test-lagrange3 SOURCES test-lagrange.cc COMPILE_DEFINITIONS "CHECKDIM=3") dune_add_test(NAME test-lagrange4 SOURCES test-lagrange.cc COMPILE_DEFINITIONS "CHECKDIM=4" TIMEOUT 600) dune_add_test(NAME test-orthonormal1 SOURCES test-orthonormal.cc COMPILE_DEFINITIONS "CHECKDIM=1") dune_add_test(NAME test-orthonormal2 SOURCES test-orthonormal.cc COMPILE_DEFINITIONS "CHECKDIM=2") dune_add_test(NAME test-orthonormal3 SOURCES test-orthonormal.cc COMPILE_DEFINITIONS "CHECKDIM=3") dune_add_test(NAME test-orthonormal4 SOURCES test-orthonormal.cc COMPILE_DEFINITIONS "CHECKDIM=4") dune_add_test(NAME test-raviartthomassimplex1 SOURCES test-raviartthomassimplex.cc COMPILE_DEFINITIONS "CHECKDIM=1") dune_add_test(NAME test-raviartthomassimplex2 SOURCES test-raviartthomassimplex.cc COMPILE_DEFINITIONS "CHECKDIM=2") dune_add_test(NAME test-raviartthomassimplex3 SOURCES test-raviartthomassimplex.cc COMPILE_DEFINITIONS "CHECKDIM=3") dune_add_test(NAME test-raviartthomassimplex4 SOURCES test-raviartthomassimplex.cc COMPILE_DEFINITIONS "CHECKDIM=4") dune_add_test(NAME test-nedelecsimplex2 SOURCES test-nedelecsimplex.cc COMPILE_DEFINITIONS "CHECKDIM=2") dune_add_test(NAME test-nedelecsimplex3 SOURCES test-nedelecsimplex.cc COMPILE_DEFINITIONS "CHECKDIM=3") dune-localfunctions-2.8.0/dune/localfunctions/test/bdfmelementtest.cc000066400000000000000000000010661411343327200261260ustar00rootroot00000000000000#include "config.h" #include #include #include int main(int argc, char** argv) { bool success = true; Dune::BDFMCubeLocalFiniteElement bdfm1cube2dlfem(1); TEST_FE(bdfm1cube2dlfem); Dune::BDFMCubeLocalFiniteElement bdfm2cube2dlfem(1); TEST_FE(bdfm2cube2dlfem); Dune::BDFMCubeLocalFiniteElement bdfm3cube2dlfem(1); TEST_FE(bdfm3cube2dlfem); return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/brezzidouglasmarinielementtest.cc000066400000000000000000000021741411343327200313030ustar00rootroot00000000000000// -*- 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 int main(int argc, char** argv) { bool success = true; Dune::BrezziDouglasMariniCubeLocalFiniteElement bdm1cube2dlfem(1); TEST_FE(bdm1cube2dlfem); Dune::BrezziDouglasMariniCubeLocalFiniteElement bdm1cube3dlfem(1); // \todo Implement the missing LocalInterpolation // DisableRepresentConstants is only set because the test also uses DisableLocalInterpolation internally. TEST_FE2(bdm1cube3dlfem, DisableLocalInterpolation + DisableRepresentConstants); Dune::BrezziDouglasMariniCubeLocalFiniteElement bdm2cube2dlfem(1); TEST_FE(bdm2cube2dlfem); Dune::BrezziDouglasMariniSimplexLocalFiniteElement bdm1simplex2dlfem(1); TEST_FE(bdm1simplex2dlfem); Dune::BrezziDouglasMariniSimplexLocalFiniteElement bdm2simplex2dlfem(1); TEST_FE(bdm2simplex2dlfem); return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/crouzeixraviartelementtest.cc000066400000000000000000000015741411343327200304630ustar00rootroot00000000000000// -*- 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 int main(int argc, char** argv) { bool success = true; Dune::CrouzeixRaviartLocalFiniteElement crozeixRaviart1dLFE; TEST_FE3(crozeixRaviart1dLFE, DisableNone, 2 /* difforder */); Dune::CrouzeixRaviartLocalFiniteElement crozeixRaviart2dLFE; TEST_FE3(crozeixRaviart2dLFE, DisableNone, 2 /* difforder */); Dune::CrouzeixRaviartLocalFiniteElement crozeixRaviart3dLFE; TEST_FE3(crozeixRaviart3dLFE, DisableNone, 2 /* difforder */); Dune::CrouzeixRaviartLocalFiniteElement crozeixRaviart4dLFE; TEST_FE3(crozeixRaviart4dLFE, DisableNone, 2 /* difforder */); return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/dualmortarelementtest.cc000066400000000000000000000014671411343327200273750ustar00rootroot00000000000000// -*- 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 "test-localfe.hh" int main(int argc, char** argv) { bool success = true; 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); return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/geometries.hh000066400000000000000000000135451411343327200251260ustar00rootroot00000000000000// -*- 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 = Dune::GeometryTypes::vertex; 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 = Dune::GeometryTypes::line; 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 = Dune::GeometryTypes::triangle; 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 = Dune::GeometryTypes::quadrilateral; 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 = Dune::GeometryTypes::tetrahedron; 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 = Dune::GeometryTypes::pyramid; 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 = Dune::GeometryTypes::prism; 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 = Dune::GeometryTypes::hexahedron; 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.8.0/dune/localfunctions/test/globalmonomialfunctionstest.cc000066400000000000000000000034071411343327200305720ustar00rootroot00000000000000// -*- 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 "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(std::make_index_sequence<4>{},[&](auto i){Order(result);}); } int main(int argc, char** argv) { try { int result = 77; Dune::Hybrid::forEach(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.8.0/dune/localfunctions/test/hierarchicalelementtest.cc000066400000000000000000000016471411343327200276410ustar00rootroot00000000000000// -*- 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 int main(int argc, char** argv) { bool success = true; 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); return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/lagrangeshapefunctiontest.cc000066400000000000000000000221561411343327200302160ustar00rootroot00000000000000// -*- 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 #include #include #include #include #include #include #include #include #include #include #include /** \file \brief Performs some tests for the Lagrange shape functions */ 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 bool testPk(const FE& local_fe) { 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; return false; } } return true; } int main (int argc, char *argv[]) { #if __linux__ \ && (!defined __INTEL_COMPILER || __INTEL_COMPILER >= 1010) \ && (!defined __clang__) feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW); #endif bool success = true; ////////////////////////////////////////////////////////// // Test for the Lagrange property ////////////////////////////////////////////////////////// P1LocalFiniteElement p11d; success &= testPk(p11d); P1LocalFiniteElement p12d; success &= testPk(p12d); P1LocalFiniteElement p13d; success &= testPk(p13d); // P23DLocalFiniteElement does not fulfill above assumption on the // ordering of the shape functions // P23DLocalFiniteElement p23d; // testPk(p23d); Pk2DLocalFiniteElement pk12d; success &= testPk(pk12d); Pk2DLocalFiniteElement pk22d; success &= testPk(pk22d); Pk2DLocalFiniteElement pk32d; success &= testPk(pk32d); Pk2DLocalFiniteElement pk42d; success &= testPk(pk42d); Pk3DLocalFiniteElement pk13d; success &= testPk(pk13d); Pk3DLocalFiniteElement pk23d; success &= testPk(pk23d); Pk3DLocalFiniteElement pk33d; success &= testPk(pk33d); Pk3DLocalFiniteElement pk43d; success &= testPk(pk43d); ////////////////////////////////////////////////////////// // Run the standard tests ////////////////////////////////////////////////////////// P0LocalFiniteElement p0lfem( GeometryTypes::simplex(2)); TEST_FE(p0lfem); P1LocalFiniteElement p11dlfem; TEST_FE3(p11dlfem,DisableNone,2); P1LocalFiniteElement p12dlfem; TEST_FE3(p12dlfem,DisableNone,2); P1LocalFiniteElement p13dlfem; TEST_FE3(p13dlfem,DisableNone,2); Q1LocalFiniteElement q11dlfem; TEST_FE(q11dlfem); Q1LocalFiniteElement q12dlfem; TEST_FE(q12dlfem); Q1LocalFiniteElement q13dlfem; TEST_FE(q13dlfem); Pk1DLocalFiniteElement p11dfem; TEST_FE(p11dfem); PQ22DLocalFiniteElement pq22dlfem( GeometryTypes::simplex(2)); TEST_FE(pq22dlfem); P23DLocalFiniteElement p23dlfem; TEST_FE(p23dlfem); PrismP1LocalFiniteElement prismp1fem; TEST_FE3(prismp1fem, DisableNone, 2); PrismP2LocalFiniteElement prismp2fem; TEST_FE3(prismp2fem, DisableNone, 1); // Pyramid shapefunctions are not differentiable on the plane where xi[0]=xi[1]. // So let's skip test points on this plane auto xySkip = [](const FieldVector& xi){return std::abs(xi[0]-xi[1]) < 1e-8;}; PyramidP1LocalFiniteElement pyramidp1fem; TEST_FE4(pyramidp1fem, DisableNone, 1, xySkip); PyramidP2LocalFiniteElement pyramidp2fem; TEST_FE4(pyramidp2fem, DisableNone, 1, xySkip); Hybrid::forEach(std::make_index_sequence<4>{},[&success](auto i) { PkLocalFiniteElement pklfem; TEST_FE(pklfem); }); Hybrid::forEach(std::make_index_sequence<5>{},[&success](auto i) { PkLocalFiniteElement pklfem; TEST_FE3(pklfem,DisableNone,2); }); Hybrid::forEach(std::make_index_sequence<6>{},[&success](auto i) { PkLocalFiniteElement pklfem; TEST_FE(pklfem); }); // -------------------------------------------------------- // Test some instantiations of QkLocalFiniteElement // -------------------------------------------------------- QkLocalFiniteElement qk11dlfem; TEST_FE3(qk11dlfem,DisableNone,2); QkLocalFiniteElement qk02dlfem; TEST_FE3(qk02dlfem,DisableNone,2); QkLocalFiniteElement qk12dlfem; TEST_FE3(qk12dlfem,DisableNone,2); QkLocalFiniteElement qk22dlfem; TEST_FE3(qk22dlfem,DisableNone,2); QkLocalFiniteElement qk32dlfem; TEST_FE3(qk32dlfem,DisableNone,2); QkLocalFiniteElement qk03dlfem; TEST_FE3(qk03dlfem,DisableNone,2); QkLocalFiniteElement qk13dlfem; TEST_FE3(qk13dlfem,DisableNone,2); QkLocalFiniteElement qk23dlfem; TEST_FE3(qk23dlfem,DisableNone,2); QkLocalFiniteElement qk33dlfem; TEST_FE3(qk33dlfem,DisableNone,2); // test virtualized FEs // notice that testFE add another level of virtualization LocalFiniteElementVirtualImp< P1LocalFiniteElement > p12dlfemVirtual(p12dlfem); TEST_FE(p12dlfemVirtual); LocalFiniteElementVirtualImp< PQ22DLocalFiniteElement > pq22dlfemVirtual(pq22dlfem); TEST_FE(pq22dlfemVirtual); LocalFiniteElementVirtualImp< LocalFiniteElementVirtualImp< P1LocalFiniteElement > > p12dlfemVirtualVirtual(p12dlfemVirtual); TEST_FE(p12dlfemVirtualVirtual); LocalFiniteElementVirtualImp< LocalFiniteElementVirtualImp< PQ22DLocalFiniteElement > > pq22dlfemVirtualVirtual(pq22dlfemVirtual); TEST_FE(pq22dlfemVirtualVirtual); typedef LocalFiniteElementVirtualInterface< P1LocalFiniteElement::Traits::LocalBasisType::Traits > Interface; TEST_FE(static_cast(p12dlfemVirtual)); // Test the LagrangeLocalFiniteElementCache LagrangeLocalFiniteElementCache lagrangeLFECache; TEST_FE(lagrangeLFECache.get(GeometryTypes::simplex(2))); TEST_FE(lagrangeLFECache.get(GeometryTypes::cube(2))); // Test whether asking the cache for an element of the wrong dimension throws an exception bool lagrangeLFESuccess = false; try { auto doesntExist = lagrangeLFECache.get(GeometryTypes::simplex(1)); } catch (Dune::Exception& e) { lagrangeLFESuccess = true; } success &= lagrangeLFESuccess; return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/monomialshapefunctiontest.cc000066400000000000000000000065421411343327200302520ustar00rootroot00000000000000// -*- 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 monomial shape functions */ double epsilon = 1e-8; using namespace Dune; template bool testShapeFunctionValue(const GeometryType& gt, const 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; return false; } return true; } int main (int argc, char *argv[]) { bool success = true; // Do the standard shape function tests std::cout << "Monomials are only tested up to order 2 due to the instability of interpolate()." << std::endl; Hybrid::forEach(std::make_index_sequence<3>{},[&success](auto i) { Dune::MonomialLocalFiniteElement monom1d(GeometryTypes::line); TEST_FE(monom1d); Dune::MonomialLocalFiniteElement monom2d(GeometryTypes::triangle); TEST_FE(monom2d); Dune::MonomialLocalFiniteElement monom3d(GeometryTypes::tetrahedron); TEST_FE(monom3d); }); // Test whether the shape function values are correct // dim=1 success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {0}, 0, 1); success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {0}, 1, 0); success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {0}, 2, 0); success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {0.5}, 0, 1); success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {0.5}, 1, .5); success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {0.5}, 2, .25); success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {1}, 0, 1); success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {1}, 1, 1); success &= testShapeFunctionValue<1,2>(GeometryTypes::line, {1}, 2, 1); // dim=2 success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {0,0}, 0, 1); success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {0,0}, 1, 0); success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {0,0}, 2, 0); success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {0.5,0.5}, 0, 1); success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {0.5,0.5}, 1, .5); success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {0.5,0.5}, 2, .5); success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {1,1}, 0, 1); success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {1,1}, 1, 1); success &= testShapeFunctionValue<2,1>(GeometryTypes::quadrilateral, {1,1}, 2, 1); return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/nedelec1stkindelementtest.cc000066400000000000000000000035651411343327200301210ustar00rootroot00000000000000// -*- 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 using namespace Dune; int main(int argc, char** argv) { bool success = true; // First order on a triangle Nedelec1stKindSimplexLocalFiniteElement nedelecLFEMTriangle1stOrder; TEST_FE3(nedelecLFEMTriangle1stOrder, DisableNone, 2); for (unsigned int s = 0; s < 8; s++) { Nedelec1stKindSimplexLocalFiniteElement nedelecLFEMTriangle1stOrder(s); TEST_FE3(nedelecLFEMTriangle1stOrder, DisableNone, 2); } // First order on a tetrahedron Nedelec1stKindSimplexLocalFiniteElement nedelecLFEMTetrahedron1stOrder; TEST_FE3(nedelecLFEMTetrahedron1stOrder, DisableNone, 2); for (unsigned int s = 0; s < 64; s++) { Nedelec1stKindSimplexLocalFiniteElement nedelecLFEMTetrahedron1stOrder(s); TEST_FE3(nedelecLFEMTetrahedron1stOrder, DisableNone, 2); } // First order on a square Nedelec1stKindCubeLocalFiniteElement nedelecLFEMSquare1stOrder; TEST_FE3(nedelecLFEMSquare1stOrder, DisableNone, 2); for (unsigned int s = 0; s < 16; s++) { Nedelec1stKindCubeLocalFiniteElement nedelecLFEMSquare1stOrder(s); TEST_FE3(nedelecLFEMSquare1stOrder, DisableNone, 2); } // First order on a cube Nedelec1stKindCubeLocalFiniteElement nedelecLFEMCube1stOrder; TEST_FE3(nedelecLFEMCube1stOrder, DisableNone, 2); for (unsigned int s = 0; s < 4096; s++) { Nedelec1stKindCubeLocalFiniteElement nedelecLFEMCube1stOrder(s); TEST_FE3(nedelecLFEMCube1stOrder, DisableNone, 2); } return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/rannacherturekelementtest.cc000066400000000000000000000011301411343327200302220ustar00rootroot00000000000000// -*- 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 int main(int argc, char** argv) { bool success = true; Dune::RannacherTurekLocalFiniteElement rannacher_turek2dfem; TEST_FE(rannacher_turek2dfem); Dune::RannacherTurekLocalFiniteElement rannacher_turek3dfem; TEST_FE(rannacher_turek3dfem); return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/raviartthomaselementtest.cc000066400000000000000000000124401411343327200301000ustar00rootroot00000000000000// -*- 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 int main(int argc, char** argv) { bool success = true; Dune::RaviartThomasSimplexLocalFiniteElement<2,double,double> rt0simplex2dlfem(Dune::GeometryTypes::simplex(2),0); TEST_FE(rt0simplex2dlfem); Dune::RaviartThomasSimplexLocalFiniteElement<2,double,double> rt1simplex2dlfem(Dune::GeometryTypes::simplex(2),1); TEST_FE(rt1simplex2dlfem); Dune::RaviartThomasSimplexLocalFiniteElement<3,double,double> rt0simplex3dlfem(Dune::GeometryTypes::simplex(3),0); TEST_FE(rt0simplex3dlfem); Dune::RaviartThomasCubeLocalFiniteElement rt0cube2dlfem; TEST_FE(rt0cube2dlfem); for (unsigned int s = 0; s < 16; s++) { Dune::RaviartThomasCubeLocalFiniteElement rt0cube2dlfem(s); TEST_FE(rt0cube2dlfem); } Dune::RaviartThomasCubeLocalFiniteElement rt0cube3dlfem; TEST_FE(rt0cube3dlfem); for (unsigned int s = 0; s < 64; s++) { Dune::RaviartThomasCubeLocalFiniteElement rt0cube3dlfem(s); TEST_FE(rt0cube3dlfem); } Dune::RaviartThomasCubeLocalFiniteElement rt1cube2dlfem; TEST_FE(rt1cube2dlfem); for (unsigned int s = 0; s < 16; s++) { Dune::RaviartThomasCubeLocalFiniteElement rt1cube2dlfem(s); TEST_FE(rt1cube2dlfem); } Dune::RaviartThomasCubeLocalFiniteElement rt1cube3dlfem; TEST_FE(rt1cube3dlfem); for (unsigned int s = 0; s < 64; s++) { Dune::RaviartThomasCubeLocalFiniteElement rt1cube3dlfem(s); TEST_FE(rt1cube3dlfem); } Dune::RaviartThomasCubeLocalFiniteElement rt2cube2dlfem; TEST_FE(rt2cube2dlfem); for (unsigned int s = 0; s < 16; s++) { Dune::RaviartThomasCubeLocalFiniteElement rt2cube2dlfem(s); TEST_FE(rt2cube2dlfem); } Dune::RaviartThomasCubeLocalFiniteElement rt3cube2dlfem; TEST_FE(rt3cube2dlfem); for (unsigned int s = 0; s < 64; s++) { Dune::RaviartThomasCubeLocalFiniteElement rt3cube2dlfem(s); TEST_FE(rt3cube2dlfem); } Dune::RaviartThomasCubeLocalFiniteElement rt4cube2dlfem; TEST_FE(rt4cube2dlfem); for (unsigned int s = 0; s < 16; s++) { Dune::RaviartThomasCubeLocalFiniteElement rt4cube2dlfem(s); TEST_FE(rt4cube2dlfem); } Dune::RT0Cube2DLocalFiniteElement rt0cube2dlfemDedicated; TEST_FE(rt0cube2dlfemDedicated); for (unsigned int s = 0; s < 16; s++) { Dune::RT0Cube2DLocalFiniteElement rt0cube2dlfemDedicated(s); TEST_FE(rt0cube2dlfemDedicated); } Dune::RT1Cube2DLocalFiniteElement rt1cube2dlfemDedicated; TEST_FE(rt1cube2dlfemDedicated); for (unsigned int s = 0; s < 16; s++) { Dune::RT1Cube2DLocalFiniteElement rt1cube2dlfemDedicated(s); TEST_FE(rt1cube2dlfemDedicated); } Dune::RT02DLocalFiniteElement rt02dlfemDedicated; TEST_FE(rt02dlfemDedicated); for (unsigned int s = 0; s < 8; s++) { Dune::RT02DLocalFiniteElement rt02dlfemDedicated(s); TEST_FE(rt02dlfemDedicated); } Dune::RT12DLocalFiniteElement rt12dlfemDedicated; TEST_FE(rt12dlfemDedicated); for (unsigned int s = 0; s < 8; s++) { Dune::RT12DLocalFiniteElement rt12dlfemDedicated(s); TEST_FE(rt12dlfemDedicated); } Dune::RT03DLocalFiniteElement rt03dlfemDedicated; TEST_FE(rt03dlfemDedicated); for (unsigned int s = 0; s < 16; s++) { Dune::RT03DLocalFiniteElement rt03dlfemDedicated(s); TEST_FE(rt03dlfemDedicated); } Dune::RT0Cube3DLocalFiniteElement rt0cube3dlfemDedicated; TEST_FE(rt0cube3dlfemDedicated); for (unsigned int s = 0; s < 64; s++) { Dune::RT0Cube3DLocalFiniteElement rt0cube3dlfemDedicated(s); TEST_FE(rt0cube3dlfemDedicated); } Dune::RT1Cube3DLocalFiniteElement rt1cube3dlfemDedicated; TEST_FE(rt1cube3dlfemDedicated); for (unsigned int s = 0; s < 64; s++) { Dune::RT1Cube3DLocalFiniteElement rt1cube3dlfemDedicated(s); TEST_FE(rt1cube3dlfemDedicated); } // Test the RaviartThomasLocalFiniteElementCache Dune::RaviartThomasLocalFiniteElementCache lagrangeLFECache; TEST_FE(lagrangeLFECache.get(Dune::GeometryTypes::simplex(2))); TEST_FE(lagrangeLFECache.get(Dune::GeometryTypes::cube(2))); // Test whether asking the cache for an element of the wrong dimension throws an exception bool lagrangeLFESuccess = false; try { auto doesntExist = lagrangeLFECache.get(Dune::GeometryTypes::simplex(1)); } catch (Dune::Exception& e) { lagrangeLFESuccess = true; } success &= lagrangeLFESuccess; return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/refinedelementtest.cc000066400000000000000000000015071411343327200266320ustar00rootroot00000000000000// -*- 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 int main(int argc, char** argv) { bool success = true; 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); return success ? 0 : 1; } dune-localfunctions-2.8.0/dune/localfunctions/test/test-edges0.5.cc000066400000000000000000000032101411343327200252240ustar00rootroot00000000000000// -*- 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(Dune::GeometryTypes::simplex(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.8.0/dune/localfunctions/test/test-fe.hh000066400000000000000000000245731411343327200243350ustar00rootroot00000000000000// -*- 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 { const FE& fe; public: using RangeType = typename FE::Traits::Basis::Traits::Range; using DomainType = typename FE::Traits::Basis::Traits::DomainLocal; struct Traits { using RangeType = typename FE::Traits::Basis::Traits::Range; using DomainType = typename FE::Traits::Basis::Traits::DomainLocal; }; 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; std::vector::CT> coeff2; for(int i=0; i() << ":" << std::endl; success = false; } // Check size of weight vector if (coeff.size() != fe.basis().size()) { std::cout << "Bug in LocalInterpolation for finite element type " << Dune::className() << ":" << 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.8.0/dune/localfunctions/test/test-finiteelementcache.cc000066400000000000000000000044731411343327200275420ustar00rootroot00000000000000// -*- 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 template static void test(Dune::GeometryType type) { FiniteElementCache cache; using FiniteElement = typename FiniteElementCache::FiniteElementType; [[maybe_unused]] const FiniteElement& finiteElement = cache.get(type); } int main() { static constexpr std::size_t max_k = 3; Dune::Hybrid::forEach(std::make_index_sequence{},[&](auto k) { constexpr int dim = 2; using FiniteElementCache = typename Dune::PQkLocalFiniteElementCache; test(Dune::GeometryTypes::simplex(dim)); test(Dune::GeometryTypes::cube(dim)); }); { constexpr int dim = 2; using FiniteElementCache = typename Dune::DualPQ1LocalFiniteElementCache; test(Dune::GeometryTypes::simplex(dim)); test(Dune::GeometryTypes::cube(dim)); } { constexpr int dim = 2; constexpr int order = 0; using FiniteElementCache = typename Dune::RaviartThomasLocalFiniteElementCache; test(Dune::GeometryTypes::simplex(dim)); test(Dune::GeometryTypes::cube(dim)); } { constexpr int dim = 2; constexpr int order = 1; using FiniteElementCache = typename Dune::RaviartThomasLocalFiniteElementCache; test(Dune::GeometryTypes::simplex(dim)); test(Dune::GeometryTypes::cube(dim)); } { constexpr int dim = 3; constexpr int order = 0; using FiniteElementCache = typename Dune::RaviartThomasLocalFiniteElementCache; test(Dune::GeometryTypes::simplex(dim)); test(Dune::GeometryTypes::cube(dim)); } return 0; } dune-localfunctions-2.8.0/dune/localfunctions/test/test-lagrange.cc000066400000000000000000000125761411343327200255110ustar00rootroot00000000000000// -*- 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 Lagrange * shape functions on simplices. * * The topology can be chosen at compile time by setting TOPOLOGY * to a Dune::GeometryType like * \code * GeometryTypes::simplex(2) * \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) { constexpr Dune::GeometryType geometry = geometryId; typedef Dune::LagrangeBasisFactory BasisFactory; typedef Dune::LagrangeCoefficientsFactory< Dune::EquidistantPointSet, geometry.dim(), double > LagrangeCoefficientsFactory; bool ret = true; for (unsigned int o = 0; o <= order; ++o) { const typename LagrangeCoefficientsFactory::Object *pointsPtr = LagrangeCoefficientsFactory::template create< geometry >( o ); if ( pointsPtr == 0) continue; std::cout << "Testing " << geometry << " 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_" << geometry << "_p" << o << ".basis"; std::ofstream out(name.str().c_str()); Dune::basisPrint<0,BasisFactory,typename BasisFactory::StorageField,geometry>(out,basis); Dune::basisPrint<1,BasisFactory,typename BasisFactory::StorageField,geometry>(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; } #ifdef CHECKDIM #if CHECKDIM==1 #define CHECKDIM1 #elif CHECKDIM==2 #define CHECKDIM2 #elif CHECKDIM==3 #define CHECKDIM3 #elif CHECKDIM==4 #define CHECKDIM4 #endif #else #define CHECKDIM1 #define CHECKDIM2 #define CHECKDIM3 #define CHECKDIM4 #endif int main ( int argc, char **argv ) { using namespace Dune; using namespace Impl; 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; #ifdef CHECKDIM1 tests &= test (order); tests &= test (order); #endif #ifdef CHECKDIM2 tests &= test (order); tests &= test (order); #endif #ifdef CHECKDIM3 tests &= test (order); tests &= test (order); tests &= test (order); tests &= test (order); #endif // reduce tested order to 4 in 4d unless explicitly asked for more if (argc < 2) order = 4; #ifdef CHECKDIM4 tests &= test (order); tests &= test (order); #endif return (tests ? 0 : 1); #endif // TOPOLOGY } dune-localfunctions-2.8.0/dune/localfunctions/test/test-localfe.hh000066400000000000000000000764421411343327200253520ustar00rootroot00000000000000// -*- 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 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) // This class wraps one shape function of a local finite element as a function // that can be feed to the LocalInterpolation::interpolate method. template class ShapeFunctionAsFunction { public: typedef typename FE::Traits::LocalBasisType::Traits::DomainType DomainType; typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType; struct Traits { typedef typename FE::Traits::LocalBasisType::Traits::DomainType DomainType; typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType; }; typedef typename FE::Traits::LocalBasisType::Traits::RangeFieldType CT; ShapeFunctionAsFunction(const FE& fe, int shapeFunction) : fe_(fe), shapeFunction_(shapeFunction) {} void evaluate (const DomainType& x, RangeType& y) const { std::vector yy; fe_.localBasis().evaluateFunction(x, yy); y = yy[shapeFunction_]; } private: const FE& fe_; int shapeFunction_; }; // This class wraps one shape function of a local finite element as a callable // that can be fed to the LocalInterpolation::interpolate method. template class ShapeFunctionAsCallable { // These types are deliberately private: They are not part of a Callable API typedef typename FE::Traits::LocalBasisType::Traits::DomainType DomainType; typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType; public: ShapeFunctionAsCallable(const FE& fe, int shapeFunction) : fe_(fe), shapeFunction_(shapeFunction) {} RangeType operator() (DomainType x) const { std::vector yy; fe_.localBasis().evaluateFunction(x, yy); return yy[shapeFunction_]; } private: const FE& fe_; int shapeFunction_; }; // Check whether the degrees of freedom computed by LocalInterpolation // are dual to the shape functions. See Ciarlet, "The Finite Element Method // for Elliptic Problems", 1978, for details. template bool testLocalInterpolation(const FE& fe) { std::vector::CT> coeff; for(size_t i=0; i f(fe, i); // Compute degrees of freedom for that shape function // We expect the result to be the i-th unit vector fe.localInterpolation().interpolate(f, coeff); // Check size of weight vector if (coeff.size() != fe.localBasis().size()) { std::cout << "Bug in LocalInterpolation for finite element type " << Dune::className(fe) << std::endl; std::cout << " Interpolation produces " << coeff.size() << " degrees of freedom" << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } // Check if interpolation weights are equal to coefficients for(std::size_t j=0; j TOL) { std::cout << std::setprecision(16); std::cout << "Bug in LocalInterpolation for finite element type " << Dune::className(fe) << std::endl; std::cout << " Degree of freedom " << j << " applied to shape function " << i << " yields value " << coeff[j] << ", not the expected value " << (i==j) << std::endl; std::cout << std::endl; return false; } } ////////////////////////////////////////////////////////////////////////////// // Part B: Redo the same test, but feed the shape functions to the // 'interpolate' method in form of a callable. ////////////////////////////////////////////////////////////////////////////// // The i-th shape function as a function that 'interpolate' can deal with ShapeFunctionAsCallable sfAsCallable(fe, i); // Compute degrees of freedom for that shape function // We expect the result to be the i-th unit vector fe.localInterpolation().interpolate(sfAsCallable, coeff); // Check size of weight vector if (coeff.size() != fe.localBasis().size()) { std::cout << "Bug in LocalInterpolation for finite element type " << Dune::className(fe) << std::endl; std::cout << " Interpolation produces " << coeff.size() << " degrees of freedom" << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } // Check if interpolation weights are equal to coefficients for(std::size_t j=0; j TOL) { std::cout << std::setprecision(16); std::cout << "Bug in LocalInterpolation for finite element type " << Dune::className(fe) << std::endl; std::cout << " Degree of freedom " << j << " applied to shape function " << i << " yields value " << coeff[j] << ", not the expected value " << (i==j) << std::endl; std::cout << std::endl; return false; } } } return true; } // Check whether the space spanned by the shape functions // contains the constant functions template bool testCanRepresentConstants(const FE& fe, unsigned order = 5) { typedef typename FE::Traits::LocalBasisType LB; using RangeType = typename LB::Traits::RangeType; bool success = true; // Construct the constant '1' function auto constantOne = [](const typename LB::Traits::DomainType& xi) { return RangeType(1.0); }; // Project the constant function onto the FE space std::vector coefficients; fe.localInterpolation().interpolate(constantOne, coefficients); // 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 values; fe.localBasis().evaluateFunction(testPoint, values); RangeType sum(0); for (size_t j=0; j TOL) { std::cout << "Finite element type " << Dune::className(fe) << " cannot represent constant functions!" << std::endl; std::cout << " At position: " << testPoint << "," << std::endl; std::cout << " discrete approximation of the '1' function has value " << sum << std::endl; std::cout << std::endl; success = false; } } // Loop over all quadrature points return success; } // check whether Jacobian agrees with FD approximation template bool testJacobian(const FE& fe, unsigned order = 2, const std::function derivativePointSkip = nullptr) { 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 evaluateJacobian() 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; } // Skip this test point if we are supposed to if (derivativePointSkip && derivativePointSkip(quad[i].position())) continue; // Loop over all directions for (int k=0; k 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 shape functions in this set for (unsigned int j=0; j 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 shape functions in this set } // Loop over all directions } // Loop over all quadrature points return success; } /** \brief Helper class to test the 'partial' method * * It implements a static loop over the available diff orders */ struct TestPartial { template static bool test(const FE& fe, double eps, double delta, unsigned int diffOrder, std::size_t order = 2, const std::function derivativePointSkip = nullptr) { bool success = true; if (diffOrder > 2) std::cout << "No test for differentiability orders larger than 2!" << std::endl; if (diffOrder >= 2) success = success and testOrder2(fe, eps, delta, order, derivativePointSkip); if (diffOrder >= 1) success = success and testOrder1(fe, eps, delta, order, derivativePointSkip); success = success and testOrder0(fe, eps, delta, order); return success; } /** \brief Test the 'partial' method for zero-order partial derivatives, i.e., values */ template static bool testOrder0(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 Test the 'partial' method for first-order partial derivatives */ template static bool testOrder1(const FE& fe, double eps, double delta, std::size_t order = 2, const std::function derivativePointSkip = nullptr) { 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(); // Skip the test points we are supposed to skip if (derivativePointSkip && derivativePointSkip(testPoint)) continue; // Loop over all directions for (int k = 0; k < LB::Traits::dimDomain; k++) { // 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 partial() for finite element type " << Dune::className(fe) << std::endl; std::cout << " firstPartialDerivatives vector has size " << firstPartialDerivatives.size() << std::endl; std::cout << " Basis has size " << fe.localBasis().size() << std::endl; std::cout << std::endl; return false; } // 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 shape functions in this set for (unsigned int j = 0; j < fe.localBasis().size(); ++j) { // Loop over all components for (int l = 0; l < LB::Traits::dimRange; ++l) { RangeField finiteDiff = (upValues[j][l] - downValues[j][l]) / (2 * jacobianTOL); // 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 " << partialDerivative << ", but " << finiteDiff << " is expected." << std::endl; std::cout << std::endl; success = false; } } // Loop over all directions } // Loop over all shape functions in this set } //Loop over all components } // Loop over all quadrature points return success; } /** \brief Test second-order partial derivatives */ template static bool testOrder2(const FE& fe, double eps, double delta, std::size_t order = 2, const std::function derivativePointSkip = nullptr) { 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(); // Skip the test points we are supposed to skip if (derivativePointSkip && derivativePointSkip(testPoint)) continue; // 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++) { // 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 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 shape functions in this set for (std::size_t j = 0; j < fe.localBasis().size(); ++j) { //Loop over all components for (std::size_t k = 0; k < dimR; ++k) { RangeField finiteDiff = (neighbourValues[0][j][k] - neighbourValues[1][j][k] - neighbourValues[2][j][k] + neighbourValues[3][j][k]) / (4 * delta * delta); // 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 return success; } }; // Flags for disabling parts of testFE enum { DisableNone = 0, DisableLocalInterpolation = 1, DisableVirtualInterface = 2, DisableJacobian = 4, DisableEvaluate = 8, DisableRepresentConstants = 16 }; /** \brief Call tests for given finite element * * \param derivativePointSkip This is a small predicate class that allows to skip certain * points when testing the derivative implementations. It exists because some * finite elements are not everywhere differentiable, but we still want to run * the tests for derivatives. Rather than constructing special sets of test * points that avoid the problematic parts of the domain, we simply skip * all test points that happen to be somewhere where the shape functions are * not differentiable. */ template bool testFE(const FE& fe, char disabledTests = DisableNone, unsigned int diffOrder = 0, const std::function derivativePointSkip = nullptr) { // Order of the quadrature rule used to generate test points unsigned int quadOrder = 2; 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; } const auto& lc = fe.localCoefficients(); for(size_t i=0; i fe.type().dim()) { std::cout << "Bug in finite element type " << Dune::className(fe) << std::endl; std::cout << " Codimension reported by localKey(" << i << ") is " << lk.codim() << std::endl; std::cout << " but geometry is " << fe.type() << " with dimension " << fe.type().dim() << std::endl; success = false; } } if (not (disabledTests & DisableLocalInterpolation)) { success = testLocalInterpolation(fe) and success; } if (not (disabledTests & DisableRepresentConstants)) { success = testCanRepresentConstants(fe) and success; } if (not (disabledTests & DisableJacobian)) { success = testJacobian(fe, quadOrder, derivativePointSkip) and success; } else { // make sure diffOrder is 0 success = (diffOrder == 0) and success; } if (not (disabledTests & DisableEvaluate)) { success = TestPartial::test(fe, TOL, jacobianTOL, diffOrder, quadOrder, derivativePointSkip) and success; } if (not (disabledTests & DisableVirtualInterface)) { typedef typename FE::Traits::LocalBasisType::Traits ImplementationLBTraits; 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, quadOrder, derivativePointSkip) and success; } else { // make sure diffOrder is 0 success = (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); std::cout << "testFE(" #A ", " #B ") " << (b?"succeeded\n":"failed\n"); success &= b; } #define TEST_FE3(A,B,C) { bool b = testFE(A, B, C); std::cout << "testFE(" #A ", " #B ", " #C ") " << (b?"succeeded\n":"failed\n"); success &= b; } #define TEST_FE4(A,B,C,D) { bool b = testFE(A, B, C, D); std::cout << "testFE(" #A ", " #B ", " #C ", " #D ") " << (b?"succeeded\n":"failed\n"); success &= b; } #endif // DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH dune-localfunctions-2.8.0/dune/localfunctions/test/test-nedelecsimplex.cc000066400000000000000000000073501411343327200267240ustar00rootroot00000000000000// -*- 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 Nedelec * shape functions on simplices. * * The topology can be chosen at compile time by setting TOPOLOGY * to a Dune::GeometryType like * \code * GeometryTypes::simplex(2) * \endcode * which generates a 2d simplex. If TOPOLOGY is not set, triangles and tetrahedra * 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< Dune::GeometryType::Id geometryId > bool test(unsigned int order) { bool ret = true; constexpr Dune::GeometryType geometry = geometryId; for (unsigned int o = 1; o <= order; ++o) { std::cout << "Testing " << geometry << " of the " << o <<"-th kind"<< std::endl; typedef Dune::NedelecBasisFactory 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 << "ned_" << geometry << "_p" << o << ".basis"; std::ofstream out(name.str().c_str()); Dune::basisPrint<0, BasisFactory, typename BasisFactory::StorageField, geometry>(out,basis); Dune::basisPrint<1, BasisFactory, typename BasisFactory::StorageField, geometry>(out,basis); #endif // TEST_OUTPUT_FUNCTIONS // test interpolation typedef Dune::NedelecL2InterpolationFactory 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); std::cout<<"----------------------------------------------------------------------------------------------------------------\n"; } if (!ret) { std::cout << " FAILED !" << std::endl; } return ret; } #ifdef CHECKDIM #if CHECKDIM==2 #define CHECKDIM2 #elif CHECKDIM==3 #define CHECKDIM3 #endif #else #define CHECKDIM2 #define CHECKDIM3 #endif int main ( int argc, char **argv ) { using namespace Dune; using namespace Impl; unsigned int order = (argc < 2) ? 5 : atoi(argv[1]); if (argc < 2) { std::cerr << "Usage: " << argv[ 0 ] << "

" << std::endl << "Using default kind of " << order << std::endl; } #ifdef TOPOLOGY return (test(order) ? 0 : 1 ); #else bool tests = true; #ifdef CHECKDIM2 tests &= test(order); #endif #ifdef CHECKDIM3 tests &= test(order); #endif return (tests ? 0 : 1); #endif // TOPOLOGY } dune-localfunctions-2.8.0/dune/localfunctions/test/test-orthonormal.cc000066400000000000000000000112261411343327200262640ustar00rootroot00000000000000// -*- 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 Dune::GeometryType like * \code * GeometryTypes::simplex(2) * \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< Dune::GeometryType::Id geometryId > bool test(unsigned int order) { bool ret = true; constexpr Dune::GeometryType geometry = geometryId; for (unsigned int o = 0; o <= order; ++o) { std::cout << "Testing " << geometry << " 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(geometry,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_" << geometry << "_p" << o << ".basis"; std::ofstream out(name.str().c_str()); Dune::basisPrint<0,BasisFactory,typename BasisFactory::StorageField,geometry>(out,basis); Dune::basisPrint<1,BasisFactory,typename BasisFactory::StorageField,geometry>(out,basis); #endif // TEST_OUTPUT_FUNCTIONS BasisFactory::release(&basis); } if (!ret) { std::cout << " FAILED !" << std::endl; } std::cout << std::endl; return ret; } #ifdef CHECKDIM #if CHECKDIM==1 #define CHECKDIM1 #elif CHECKDIM==2 #define CHECKDIM2 #elif CHECKDIM==3 #define CHECKDIM3 #elif CHECKDIM==4 #define CHECKDIM4 #endif #else #define CHECKDIM1 #define CHECKDIM2 #define CHECKDIM3 #define CHECKDIM4 #endif 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; #ifdef CHECKDIM1 tests &= test (order); tests &= test (order); #endif #ifdef CHECKDIM2 tests &= test (order); tests &= test (order); #endif #ifdef CHECKDIM3 tests &= test (order); tests &= test (order); tests &= test (order); tests &= test (order); #endif #ifdef CHECKDIM4 tests &= test (order); tests &= test (order); #endif return (tests ? 0 : 1); #endif // TOPOLOGY } dune-localfunctions-2.8.0/dune/localfunctions/test/test-pk2d.cc000066400000000000000000000032601411343327200245570ustar00rootroot00000000000000// -*- 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(Dune::GeometryTypes::triangle); 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(std::make_index_sequence{},[&](auto i){test(result);}); return result; } catch (const Dune::Exception& e) { std::cerr << e << std::endl; throw; } } dune-localfunctions-2.8.0/dune/localfunctions/test/test-power-monomial.cc000066400000000000000000000046061411343327200266710ustar00rootroot00000000000000// -*- 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(std::make_index_sequence<4>{},[&](auto i){Order(result);}); } template static void DimD(int &result) { Dune::Hybrid::forEach(std::make_index_sequence<4>{},[&](auto i){DimR(result);}); } int main(int argc, char** argv) { try { int result = 77; Dune::Hybrid::forEach(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.8.0/dune/localfunctions/test/test-q1.cc000066400000000000000000000026161411343327200242440ustar00rootroot00000000000000// -*- 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(Dune::GeometryTypes::cube(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.8.0/dune/localfunctions/test/test-q2.cc000066400000000000000000000026451411343327200242470ustar00rootroot00000000000000// -*- 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(Dune::GeometryTypes::cube(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.8.0/dune/localfunctions/test/test-raviartthomassimplex.cc000066400000000000000000000077731411343327200302220ustar00rootroot00000000000000// -*- 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 Dune::GeometryType like * \code * GeometryTypes::simplex(2) * \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< Dune::GeometryType::Id geometryId > bool test(unsigned int order) { bool ret = true; constexpr Dune::GeometryType geometry = geometryId; for (unsigned int o = 0; o <= order; ++o) { std::cout << "Testing " << geometry << " 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_" << geometry << "_p" << o << ".basis"; std::ofstream out(name.str().c_str()); Dune::basisPrint<0,BasisFactory,typename BasisFactory::StorageField,geometry>(out,basis); Dune::basisPrint<1,BasisFactory,typename BasisFactory::StorageField,geometry>(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; } #ifdef CHECKDIM #if CHECKDIM==1 #define CHECKDIM1 #elif CHECKDIM==2 #define CHECKDIM2 #elif CHECKDIM==3 #define CHECKDIM3 #elif CHECKDIM==4 #define CHECKDIM4 #endif #else #define CHECKDIM1 #define CHECKDIM2 #define CHECKDIM3 #define CHECKDIM4 #endif int main ( int argc, char **argv ) { using namespace Dune; using namespace Impl; 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; #ifdef CHECKDIM1 tests &= test (order); #endif #ifdef CHECKDIM2 tests &= test (order); #endif #ifdef CHECKDIM3 tests &= test (order); #endif // reduce tested order to 4 in 4d unless explicitly asked for more if (argc < 2) order = 4; #ifdef CHECKDIM4 tests &= test (order); #endif return (tests ? 0 : 1); #endif // TOPOLOGY } dune-localfunctions-2.8.0/dune/localfunctions/test/testgenericfem.cc000066400000000000000000000100301411343327200257370ustar00rootroot00000000000000// -*- 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 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, 2, 4, 6}) { std::cout << "order : " << order << std::endl; Dune::LagrangeLocalFiniteElement lagrangeSimplex(Dune::GeometryTypes::simplex(3), order); TEST_FE(lagrangeSimplex); } std::cout << "Testing LagrangeLocalFiniteElement on 2d" << " cube elements with double precision" << std::endl; for (unsigned int order : {1, 2, 4}) { std::cout << "order : " << order << std::endl; Dune::LagrangeLocalFiniteElement lagrangeCube(Dune::GeometryTypes::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, 8}) { std::cout << "order : " << order << std::endl; Dune::LagrangeLocalFiniteElement,Dune::GMPField<256> > lagrangeSimplex(Dune::GeometryTypes::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, 2}) { std::cout << "order : " << order << std::endl; typedef Dune::LagrangeLocalFiniteElement FE; Dune::DGLocalFiniteElement dglagrangeCube(Dune::GeometryTypes::cube(3), order); TEST_FE(dglagrangeCube); } std::cout << "Testing L2LagrangeLocalFiniteElement on 3d" << " cube elements with double precision" << std::endl; for (unsigned int order : {2, 3}) { std::cout << "order : " << order << std::endl; typedef Dune::LagrangeLocalFiniteElement FE; Dune::L2LocalFiniteElement dglagrangeCube(Dune::GeometryTypes::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 : {6}) { std::cout << "order : " << order << std::endl; Dune::OrthonormalLocalFiniteElement<3,double,double, Dune::GMPField<64>,Dune::GMPField<256> > onbPrism(Dune::GeometryTypes::prism, order); TEST_FE(onbPrism); } #endif std::cout << "Testing OrthonormalFiniteElement on 3d" << " prism elements with double precision" << std::endl; for (unsigned int order : {4, 2}) { std::cout << "order : " << order << std::endl; Dune::OrthonormalLocalFiniteElement<3,double,double> onbPrism(Dune::GeometryTypes::prism, order); TEST_FE(onbPrism); } std::cout << "Testing RaviartThomasSimplexFiniteElement on 3d" << " simplex elements with double precision" << std::endl; for (unsigned int order : {0, 1, 4}) { std::cout << "order : " << order << std::endl; Dune::RaviartThomasSimplexLocalFiniteElement<3,double,double> rtSimplex(Dune::GeometryTypes::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.8.0/dune/localfunctions/test/virtualshapefunctiontest.cc000066400000000000000000000147541411343327200301310ustar00rootroot00000000000000// -*- 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 #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 { using DomainType = D; using RangeType = R; struct Traits { using DomainType = D; using RangeType = R; }; 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() ); [[maybe_unused]] unsigned int size = 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; ////////////////////////////////////////////////////////////////////////////// // Part A: Feed the function to the 'interpolate' method in form of // a class providing an evaluate() method. // This way is deprecated since dune-localfunctions 2.7. ////////////////////////////////////////////////////////////////////////////// localInterpolation->interpolate(testFunction, coefficients); ////////////////////////////////////////////////////////////////////////////// // Part B: Redo the same test, but feed the function to the // 'interpolate' method in form of a callable. ////////////////////////////////////////////////////////////////////////////// auto callableTestFunction = [&](const auto& x) { RangeType y(0); testFunction.evaluate(x,y); return y; }; localInterpolation->interpolate(callableTestFunction, coefficients); } // 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); // Test cloning const LocalFiniteElementVirtualInterface* other = localFiniteElement->clone(); // Make sure new object has the same type if (typeid(other).hash_code() != typeid(localFiniteElement).hash_code()) DUNE_THROW(Dune::Exception, "'clone' method returns object of wrong type"); // But it shouldn't be the same object if (other==localFiniteElement) DUNE_THROW(Dune::Exception, "'clone' method returned the object it was called for!"); delete other; } int main (int argc, char *argv[]) { typedef Dune::P1LocalFiniteElement::Traits::LocalBasisType::Traits LBTraits; const Dune::P0LocalFiniteElement p0FE(Dune::GeometryTypes::cube(2)); const Dune::LocalFiniteElementVirtualImp > p0VFE(p0FE); testLocalFiniteElement(&p0VFE); const Dune::PQ22DLocalFiniteElement pq2FE(Dune::GeometryTypes::cube(2)); const Dune::PQ22DLocalFiniteElement pq2FE2(pq2FE); const Dune::LocalFiniteElementVirtualImp > pq2VFE(pq2FE); testLocalFiniteElement(&pq2VFE); const Dune::LocalFiniteElementVirtualImp > p1VFE; testLocalFiniteElement(&p1VFE); const Dune::LocalFiniteElementVirtualImp< Dune::LocalFiniteElementVirtualImp > > p1VVFE; testLocalFiniteElement(&p1VVFE); typedef Dune::MonomialLocalFiniteElement Monom7; const Monom7 monom7FE(Dune::GeometryTypes::cube(2)); const Dune::LocalFiniteElementVirtualImp monom7VFE(monom7FE); const Dune::LocalFiniteElementVirtualImp< Dune::LocalFiniteElementVirtualImp > monom7VVFE(monom7VFE); testLocalFiniteElement(&monom7VVFE); return 0; } dune-localfunctions-2.8.0/dune/localfunctions/utility/000077500000000000000000000000001411343327200231565ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/utility/CMakeLists.txt000066400000000000000000000005611411343327200257200ustar00rootroot00000000000000install(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.8.0/dune/localfunctions/utility/basisevaluator.hh000066400000000000000000000105771411343327200265350ustar00rootroot00000000000000// -*- 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 DerivativeLayoutNS::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_; }; } #endif dune-localfunctions-2.8.0/dune/localfunctions/utility/basismatrix.hh000066400000000000000000000141211411343327200260240ustar00rootroot00000000000000// -*- 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< GeometryType::Id geometryId, class F, class Interpolation, class Field > struct BasisMatrix< const MonomialBasis< geometryId, F >, Interpolation, Field > : public BasisMatrixBase< const MonomialBasis< geometryId, F >, Interpolation, Field > { typedef const MonomialBasis< geometryId, 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::template create( 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< 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 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.8.0/dune/localfunctions/utility/coeffmatrix.hh000066400000000000000000000166721411343327200260220ustar00rootroot00000000000000// -*- 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 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 { static const unsigned int dimension = dim; static const unsigned int dimRange = dimR; typedef SF StorageField; typedef CF ComputeField; 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; template struct EvaluationBasisFactory { typedef typename PreBasisFactory::template EvaluationBasisFactory::Type Type; }; template< GeometryType::Id geometryId > static Object *create ( const Key &key ) { const typename PreBasisFactory::Key preBasisKey = PreBasisKeyExtractor::apply(key); const PreBasis *preBasis = PreBasisFactory::template create( preBasisKey ); const Interpolation *interpol = InterpolationFactory::template create( key ); BasisMatrix< PreBasis, Interpolation, ComputeField > matrix( *preBasis, *interpol ); const MonomialBasis *monomialBasis = MonomialBasisFactory::template create< geometryId >( preBasis->order() ); Basis *basis = new Basis( *monomialBasis ); basis->fill( matrix ); InterpolationFactory::release(interpol); PreBasisFactory::release(preBasis); return basis; } //! release the object returned by the create methods static void release( Object *object) { const MonomialBasis *monomialBasis = &(object->basis()); delete object; MonomialBasisFactory::release( monomialBasis ); } }; } #endif // #ifndef DUNE_DEFAULTBASISFACTORY_HH dune-localfunctions-2.8.0/dune/localfunctions/utility/dglocalcoefficients.hh000066400000000000000000000033741411343327200274750ustar00rootroot00000000000000// -*- 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 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 BasisFactory > struct DGLocalCoefficientsFactory { static const unsigned int dimension = BasisFactory::dimension; typedef typename BasisFactory::Key Key; typedef const DGLocalCoefficients Object; template< GeometryType::Id geometryId > static Object *create ( const Key &key ) { const typename BasisFactory::Object *basis = BasisFactory::template create< geometryId >( key ); Object *coefficients = new Object( basis->size() ); BasisFactory::release( basis ); return coefficients; } static void release( Object *object ) { delete object; } }; } #endif // #ifndef DUNE_DGLOCALCOEFFICIENTS_HH dune-localfunctions-2.8.0/dune/localfunctions/utility/field.hh000066400000000000000000000164211411343327200245660ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/utility/interpolationhelper.hh000066400000000000000000000071271411343327200275750ustar00rootroot00000000000000// -*- 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 #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 , Func>(), int> = 0> const Result &evaluate(const DomainVector &x) const { field_cast(func_(x), tmp_[0] ); return tmp_; } template , Func>(), int> = 0> 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.8.0/dune/localfunctions/utility/l2interpolation.hh000066400000000000000000000174261411343327200266360ustar00rootroot00000000000000// -*- 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 #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; /** \brief Interpolate a function that implements void evaluate(Domain, Range&) */ template< class Function, class DofField, std::enable_if_t, Function>(), int> = 0 > 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 ]; } } /** \brief Interpolate a function that implements Range operator()(Domain) */ template< class Function, class DofField, std::enable_if_t, Function>(), int> = 0 > void interpolate ( const Function &function, std::vector< DofField > &coefficients ) const { 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 >(); for (auto&& qp : quadrature()) { basis().evaluate( qp.position(), basisValues ); auto val = function( qp.position() ); RangeVector factor = field_cast< DofField >( val ); factor *= field_cast< DofField >( qp.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 { static const unsigned int dimension = BasisFactory::dimension; typedef typename BasisFactory::Key Key; typedef typename BasisFactory::Object Basis; typedef double Field; typedef QuadratureRule Quadrature; typedef QuadratureRules QuadratureProvider; typedef LocalL2Interpolation< Basis, Quadrature, onb > LocalInterpolation; typedef const LocalInterpolation Object; template< GeometryType::Id geometryId > static Object *create ( const Key &key ) { constexpr Dune::GeometryType geometry = geometryId; const Basis *basis = BasisFactory::template create< geometry >( key ); const Quadrature & quadrature = QuadratureProvider::rule(geometry, 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.8.0/dune/localfunctions/utility/lfematrix.hh000066400000000000000000000073441411343327200255020ustar00rootroot00000000000000// -*- 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 = 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.8.0/dune/localfunctions/utility/localfiniteelement.hh000066400000000000000000000135321411343327200273460ustar00rootroot00000000000000// -*- 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 #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 ) : geometry_( gt ), key_( key ), finiteElement_() { Impl::toGeometryTypeIdConstant(type(), [&](auto geometryTypeId) { finiteElement_.template create(key_); }); } /** \todo Please doc me */ GenericLocalFiniteElement ( const GenericLocalFiniteElement &other ) : geometry_( other.type() ), key_( other.key_ ), finiteElement_() { Impl::toGeometryTypeIdConstant(type(), [&](auto geometryTypeId) { finiteElement_.template create(key_); }); } ~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 geometry_; } private: struct FiniteElement { FiniteElement() : basis_(0), coeff_(0), interpol_(0) {} template < GeometryType::Id geometryId > 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; } typename Traits::LocalBasisType *basis_; typename Traits::LocalCoefficientsType *coeff_; typename Traits::LocalInterpolationType *interpol_; }; GeometryType geometry_; 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.8.0/dune/localfunctions/utility/monomialbasis.hh000066400000000000000000000557131411343327200263470ustar00rootroot00000000000000// -*- 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 normal * 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 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< GeometryType::Id geometryId, 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< GeometryType::Id geometryId, 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< GeometryType::Id geometryId > class MonomialBasisSize; template< GeometryType::Id geometryId, class F > class MonomialBasis; // MonomialBasisSize // ----------------- template< GeometryType::Id geometryId > class MonomialBasisSize { typedef MonomialBasisSize< geometryId > This; public: static This &instance () { static This _instance; return _instance; } 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 ) { if (order <= maxOrder_) return; maxOrder_ = order; delete[] sizes_; delete[] numBaseFunctions_; sizes_ = new unsigned int[ order+1 ]; numBaseFunctions_ = new unsigned int[ order+1 ]; constexpr GeometryType geometry = geometryId; constexpr auto dim = geometry.dim(); sizes_[ 0 ] = 1; for( unsigned int k = 1; k <= order; ++k ) sizes_[ k ] = 0; std::fill(numBaseFunctions_, numBaseFunctions_+order+1, 1); for( int codim=dim-1; codim>=0; codim--) { if (Impl::isPrism(geometry.id(),dim,codim)) { for( unsigned int k = 1; k <= order; ++k ) { sizes_[ k ] = numBaseFunctions_[ k ] + k*sizes_[ k ]; numBaseFunctions_[ k ] = numBaseFunctions_[ k-1 ] + sizes_[ k ]; } } else { for( unsigned int k = 1; k <= order; ++k ) { sizes_[ k ] = numBaseFunctions_[ k ]; numBaseFunctions_[ k ] = numBaseFunctions_[ k-1 ] + sizes_[ k ]; } } } } }; // MonomialBasisHelper // ------------------- template< int mydim, int dim, class F > struct MonomialBasisHelper { typedef MonomialBasisSize< GeometryTypes::simplex(mydim).toId() > MySize; typedef MonomialBasisSize< GeometryTypes::simplex(dim).toId() > 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< GeometryType::Id geometryId, class F> class MonomialBasisImpl { public: typedef F Field; static constexpr GeometryType geometry = geometryId; static const unsigned int dimDomain = geometry.dim(); typedef FieldVector< Field, dimDomain > DomainVector; private: friend class MonomialBasis< geometryId, Field >; 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 { //start with vertex *values = Unity< F >(); F *const end = values + block; for( Field *it = values+1 ; it != end; ++it ) *it = Zero< F >(); constexpr GeometryType gt = GeometryTypes::vertex; if constexpr ( geometry == gt) return; else evaluate(deriv, order, x, block, offsets, values ); } template 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 { static constexpr GeometryType baseGeometry = baseGeometryId; auto constexpr isPrismatic = geometry.isPrismatic(baseGeometry.dim()); // compute typedef MonomialBasisHelper< baseGeometry.dim() + 1, dimD, Field > Helper; typedef MonomialBasisSize BaseSize; const BaseSize &size = BaseSize::instance(); const_cast(size).computeSizes(order); const Field &z = x[ baseGeometry.dim() ]; 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 ]; if constexpr ( isPrismatic ) Helper::copy( deriv, wit, row1, k*size.sizes_[ k ], z ); Helper::copy( deriv, wit, row0, size( k-1 ), z ); row0 = row1; } // stop if desired dimension is reached if constexpr( baseGeometry.dim() == dimDomain-1) return; else { constexpr GeometryType nextGeometry = isPrismatic ? GeometryTypes::prismaticExtension(baseGeometry) : GeometryTypes::conicalExtension(baseGeometry); evaluate(deriv, order, x, block, offsets, values ); } } void integrate ( const unsigned int order, const unsigned int *const offsets, Field *const values ) const { //start with vertex values[ 0 ] = Unity< Field >(); static constexpr GeometryType gt = GeometryTypes::vertex; if constexpr ( geometry == gt) return; else integrate(order, offsets, values); } template void integrate ( const unsigned int order, const unsigned int *const offsets, Field *const values) const { static constexpr GeometryType baseGeometry = baseGeometryId; auto constexpr isPrismatic = geometry.isPrismatic(baseGeometry.dim()); // decide which kind of integration should be performed if constexpr ( isPrismatic ) integratePrismatic(order, offsets, values); else integrateConical(order, offsets, values); // stop if the desired dimension is reached if constexpr( baseGeometry.dim() == dimDomain-1) return; else { static constexpr GeometryType nextGeometry = (isPrismatic ? GeometryTypes::prismaticExtension(baseGeometry) : GeometryTypes::conicalExtension(baseGeometry)); integrate(order, offsets, values); } } template void integratePrismatic ( const unsigned int order, const unsigned int *const offsets, Field *const values ) const { typedef MonomialBasisSize BaseSize; static const BaseSize &size = BaseSize::instance(); const unsigned int *const baseSizes = size.sizes_; static constexpr GeometryType baseGeometry = baseGeometryId; static constexpr GeometryType nextGeometry = GeometryTypes::prismaticExtension(baseGeometry); typedef MonomialBasisSize Size; static const Size &mySize = Size::instance(); 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 void integrateConical ( const unsigned int order, const unsigned int *const offsets, Field *const values) const { typedef MonomialBasisSize BaseSize; static const BaseSize &size = BaseSize::instance(); const unsigned int *const baseSizes = size.sizes_; static constexpr GeometryType baseGeometry = baseGeometryId; { Field *const col0End = values + baseSizes[ 0 ]; for( Field *it = values; it != col0End; ++it ) *it *= Field( 1 ) / Field( int(baseGeometry.dim()+1) ); } Field *row0 = values; for( unsigned int k = 1; k <= order; ++k ) { const Field factor = (Field( 1 ) / Field( k + baseGeometry.dim()+1)); 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< GeometryType::Id geometryId, class F > class MonomialBasis : public MonomialBasisImpl< geometryId, F > { static constexpr GeometryType geometry = geometryId; typedef MonomialBasis< geometryId, F > This; typedef MonomialBasisImpl< geometryId, 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 { MonomialBasisSize< GeometryTypes::simplex(dimension).toId() >::instance().computeSizes( deriv ); return MonomialBasisSize< GeometryTypes::simplex(dimension).toId() >::instance() ( deriv ); } unsigned int order () const { return order_ ; } unsigned int topologyId ( ) const { return geometry.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< GeometryTypes::simplex(dim).toId() , F > { typedef StandardMonomialBasis< dim, F > This; typedef MonomialBasis< GeometryTypes::simplex(dim).toId(), F > Base; public: static constexpr GeometryType geometry = GeometryTypes::simplex(dim); static const int dimension = dim; StandardMonomialBasis ( unsigned int order ) : Base( order ) {} }; // StandardBiMonomialBasis // ----------------------- template< int dim, class F > class StandardBiMonomialBasis : public MonomialBasis< GeometryTypes::cube(dim).toId() , F > { typedef StandardBiMonomialBasis< dim, F > This; typedef MonomialBasis< GeometryTypes::cube(dim).toId() , F > Base; public: static constexpr GeometryType geometry = GeometryTypes::cube(dim); 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; [[deprecated("Use VirtualMonomialBasis(GeometryType gt, unsigned int order) instead.")]] explicit VirtualMonomialBasis(unsigned int topologyId, unsigned int order) : order_(order), geometry_(GeometryType(topologyId,dim)) {} explicit VirtualMonomialBasis(const GeometryType& gt, unsigned int order) : order_(order), geometry_(gt) {} virtual ~VirtualMonomialBasis() {} virtual const unsigned int *sizes ( ) const = 0; unsigned int size ( ) const { return sizes( )[ order_ ]; } unsigned int order () const { return order_; } [[deprecated("Use type().id() instead.")]] unsigned int topologyId ( ) const { return type().id(); } GeometryType type() const { return geometry_; } 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_; GeometryType geometry_; }; template< GeometryType::Id geometryId, class F > class VirtualMonomialBasisImpl : public VirtualMonomialBasis< static_cast(geometryId).dim(), F > { static constexpr GeometryType geometry = geometryId; typedef VirtualMonomialBasis< geometry.dim(), F > Base; typedef VirtualMonomialBasisImpl< geometryId, F > This; public: typedef typename Base::Field Field; typedef typename Base::DomainVector DomainVector; VirtualMonomialBasisImpl(unsigned int order) : Base(geometry,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 { static const unsigned int dimension = dim; typedef F StorageField; typedef unsigned int Key; typedef const VirtualMonomialBasis< dimension, F > Object; template < int dd, class FF > struct EvaluationBasisFactory { typedef MonomialBasisFactory Type; }; template< GeometryType::Id geometryId > static Object* create ( const Key &order ) { return new VirtualMonomialBasisImpl< geometryId, StorageField >( order ); } static void release( Object *object ) { delete object; } }; // 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.8.0/dune/localfunctions/utility/multiindex.hh000066400000000000000000000257251411343327200256740ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/utility/polynomialbasis.hh000066400000000000000000000307551411343327200267160ustar00rootroot00000000000000// -*- 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; template using HessianFyType = FieldVector,dimRange>; using HessianType = HessianFyType; 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 Jacobian of all shape functions void evaluateHessian (const typename Traits::DomainType& x, // position std::vector& out) const // return value { out.resize(size()); hessian(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 if (totalOrder == 1) { std::vector jacs(out.size()); unsigned int k; for (unsigned int i=0;i hesss(out.size()); int k=-1,l=-1; for (unsigned int i=0;i 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 hessian ( const DomainVector &x, std::vector> &values ) const { assert(values.size()>=size()); // only upper part of hessians matrix is computed - so we have // y[0] = FV< FV, dimRange> const unsigned int hsize = LFETensor::size; std::vector< FieldVector< FieldVector, dimRange> > y( size() ); evaluateSingle<2>( x, y ); unsigned int q=0; for (unsigned int i=0;i(x,reinterpret_cast >&>(values)); } template< class DVector, class HVector > void hessian ( const DVector &x, HVector &values ) const { assert( DVector::dimension == dimension); DomainVector bx; for( unsigned int d = 0; d < dimension; ++d ) field_cast( x[ d ], bx[ d ] ); hessian( 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.8.0/dune/localfunctions/utility/tensor.hh000066400000000000000000000716451411343327200250260ustar00rootroot00000000000000// -*- 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 namespace DerivativeLayoutNS { 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 DerivativeLayoutNS::DerivativeLayout layout = DerivativeLayoutNS::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 DerivativeLayoutNS::DerivativeLayout layout = DerivativeLayoutNS::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 DerivativeLayoutNS::derivative based layout template struct Derivatives { typedef Derivatives This; typedef Derivatives ScalarDeriv; typedef F Field; typedef F field_type; static const DerivativeLayoutNS::DerivativeLayout layout = DerivativeLayoutNS::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,DerivativeLayoutNS::derivative > &d ) { out << " ( "; out << d[0]; for (int r=1; r std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,deriv,DerivativeLayoutNS::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,DerivativeLayoutNS::derivative > &d ) { out << " ( "; out << d[0]; for (int r=1; r std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,0,DerivativeLayoutNS::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_; 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 static constexpr GeometryType type() { return GeometryTypes::simplex(Geometry::mydimension); } }; template const typename EdgeS0_5FiniteElement::Traits::Coefficients& EdgeS0_5FiniteElement::coefficients_ = typename Traits::Coefficients(); //////////////////////////////////////////////////////////////////////// // // 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.8.0/dune/localfunctions/whitney/edges0.5/000077500000000000000000000000001411343327200244545ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/localfunctions/whitney/edges0.5/CMakeLists.txt000066400000000000000000000002321411343327200272110ustar00rootroot00000000000000install(FILES basis.hh coefficients.hh common.hh interpolation.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/localfunctions/whitney/edges0.5) dune-localfunctions-2.8.0/dune/localfunctions/whitney/edges0.5/basis.hh000066400000000000000000000144461411343327200261070ustar00rootroot00000000000000// -*- 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; }; private: typedef Dune::Impl::LagrangeSimplexLocalBasis 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.8.0/dune/localfunctions/whitney/edges0.5/coefficients.hh000066400000000000000000000023471411343327200274440ustar00rootroot00000000000000// -*- 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.8.0/dune/localfunctions/whitney/edges0.5/common.hh000066400000000000000000000021661411343327200262720ustar00rootroot00000000000000// -*- 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 #include #include namespace Dune { //! Common base class for edge elements template struct EdgeS0_5Common { //! The type of the referenceElement using RefElem = decltype(referenceElement(DF{}, GeometryTypes::simplex(dim), Dim{})); //! The reference element for this edge element RefElem refelem = referenceElement(DF{}, GeometryTypes::simplex(dim), Dim{}); //! The number of base functions /** * \note This is not a compile time constant, since the number of edges is * extracted from the reference element. */ std::size_t s = refelem.size(dim-1); }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_COMMON_HH dune-localfunctions-2.8.0/dune/localfunctions/whitney/edges0.5/interpolation.hh000066400000000000000000000051171411343327200276700ustar00rootroot00000000000000// -*- 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 #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& ff, std::vector& out) const { typename Traits::Range y; auto&& f = Impl::makeFunctionWithCallOperator>(ff); out.resize(s); for(std::size_t i = 0; i < s; ++i) { y = f(refelem.position(i,dim-1)); out[i] = y * edgev[i]; } } }; } // namespace Dune #endif // DUNE_LOCALFUNCTIONS_WHITNEY_EDGES0_5_INTERPOLATION_HH dune-localfunctions-2.8.0/dune/python/000077500000000000000000000000001411343327200177515ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/python/CMakeLists.txt000066400000000000000000000000411411343327200225040ustar00rootroot00000000000000add_subdirectory(localfunctions) dune-localfunctions-2.8.0/dune/python/localfunctions/000077500000000000000000000000001411343327200227745ustar00rootroot00000000000000dune-localfunctions-2.8.0/dune/python/localfunctions/CMakeLists.txt000066400000000000000000000001551411343327200255350ustar00rootroot00000000000000install(FILES localfiniteelement.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/python/localfunctions ) dune-localfunctions-2.8.0/dune/python/localfunctions/localfiniteelement.hh000066400000000000000000000050321411343327200271600ustar00rootroot00000000000000#ifndef DUNE_PYTHON_LOCALFUNCTIONS_LOCALFINITEELEMENT_HH #define DUNE_PYTHON_LOCALFUNCTIONS_LOCALFINITEELEMENT_HH #include #include #include #include namespace Dune { namespace Python { namespace detail { template DUNE_EXPORT auto registerLocalBasis(pybind11::handle scope) { static auto cls = pybind11::class_(scope, "LocalBasis"); cls.def("__len__", [](const LocalBasis& basis) { return basis.size(); }); cls.def_property_readonly("order", [](const LocalBasis& basis) { return basis.order(); }); cls.def("evaluateFunction", [](const LocalBasis& basis, const typename LocalBasis::Traits::DomainType& in) { std::vector out; basis.evaluateFunction(in, out); return out; }); cls.def("evaluateJacobian", [](const LocalBasis& basis, const typename LocalBasis::Traits::DomainType& in) { std::vector out; basis.evaluateJacobian(in, out); return out; }); return cls; } DUNE_EXPORT auto registerLocalKey(pybind11::handle scope) { static auto cls = pybind11::class_(scope, "LocalKey"); cls.def_property_readonly("subEntity", &LocalKey::subEntity); cls.def_property_readonly("codim", &LocalKey::codim); cls.def_property("index", [](const LocalKey& key) { return key.index(); }, [](LocalKey& key, unsigned int index) { key.index(index); }); cls.def("__lt__", &LocalKey::operator<); return cls; } } /* namespace detail */ template DUNE_EXPORT auto registerLocalFiniteElement(pybind11::handle scope, const char* name = "LocalFiniteElement") { static auto cls = pybind11::class_(scope, name); detail::registerLocalBasis(cls); cls.def_property_readonly("localBasis", &LocalFiniteElement::localBasis, pybind11::return_value_policy::reference_internal); // cls.def_property_readonly("localCoefficients", &LocalFiniteElement::localCoefficients); // cls.def_property_readonly("localInterpolation", &LocalFiniteElement::localInterpolation); cls.def("__len__", &LocalFiniteElement::size); cls.def_property_readonly("type", &LocalFiniteElement::type); return cls; } } /* namespace Python */ } /* namespace Dune */ #endif dune-localfunctions-2.8.0/pyproject.toml000066400000000000000000000002451411343327200204120ustar00rootroot00000000000000[build-system] requires = ['setuptools', 'wheel', 'scikit-build', 'cmake', 'ninja', 'requests', 'dune-geometry>=2.8.0.dev0'] build-backend = 'setuptools.build_meta' dune-localfunctions-2.8.0/python/000077500000000000000000000000001411343327200170165ustar00rootroot00000000000000dune-localfunctions-2.8.0/python/CMakeLists.txt000066400000000000000000000000751411343327200215600ustar00rootroot00000000000000add_subdirectory(dune) configure_file(setup.py.in setup.py) dune-localfunctions-2.8.0/python/dune/000077500000000000000000000000001411343327200177515ustar00rootroot00000000000000dune-localfunctions-2.8.0/python/dune/CMakeLists.txt000066400000000000000000000001071411343327200225070ustar00rootroot00000000000000add_subdirectory(localfunctions) add_python_targets(dune __init__ ) dune-localfunctions-2.8.0/python/dune/__init__.py000066400000000000000000000000701411343327200220570ustar00rootroot00000000000000__import__('pkg_resources').declare_namespace(__name__) dune-localfunctions-2.8.0/python/dune/localfunctions/000077500000000000000000000000001411343327200227745ustar00rootroot00000000000000dune-localfunctions-2.8.0/python/dune/localfunctions/CMakeLists.txt000066400000000000000000000001371411343327200255350ustar00rootroot00000000000000add_python_targets(localfunctions __init__ ) dune_add_pybind11_module(NAME _localfunctions) dune-localfunctions-2.8.0/python/dune/localfunctions/__init__.py000066400000000000000000000001311411343327200251000ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals from ._localfunctions import * dune-localfunctions-2.8.0/python/dune/localfunctions/_localfunctions.cc000066400000000000000000000003071411343327200264650ustar00rootroot00000000000000#include #include PYBIND11_MODULE(_localfunctions, module) { Dune::Python::detail::registerLocalKey(module); } dune-localfunctions-2.8.0/python/setup.py.in000066400000000000000000000007111411343327200211340ustar00rootroot00000000000000from setuptools import setup, find_packages pkg = [m for m in "${ProjectPythonRequires}".split(' ') if "dune" not in m] setup(name="${ProjectName}", namespace_packages=['dune'], description="${ProjectDescription}", version="${ProjectVersionString}", author="${ProjectAuthor}", author_email="${ProjectMaintainerEmail}", packages = find_packages(), zip_safe = 0, package_data = {'': ['*.so']}, install_requires = pkg ) dune-localfunctions-2.8.0/setup.py000066400000000000000000000002411411343327200172040ustar00rootroot00000000000000try: from dune.packagemetadata import metaData except ImportError: from packagemetadata import metaData from skbuild import setup setup(**metaData()[1])