pax_global_header00006660000000000000000000000064122627726420014524gustar00rootroot0000000000000052 comment=e9f70aa78f664aa66a0ee2260e9ad923fa68c4cf ufc-2.3.0/000077500000000000000000000000001226277264200123035ustar00rootroot00000000000000ufc-2.3.0/.gitignore000066400000000000000000000004231226277264200142720ustar00rootroot00000000000000# Compiled source *.o *.Plo *.Po *.lo *.la *.a *.os *.pyc *.so *.pc *.pyd *.def *.dll *.exe *.dylib # CMake and Make files CMakeCache.txt CMakeFiles cmake_install.cmake cmake_uninstall.cmake Makefile install_manifest.txt # Temporaries *~ # OS X files .DS_Store .DS_Store? ufc-2.3.0/AUTHORS000066400000000000000000000010271226277264200133530ustar00rootroot00000000000000Authors: Martin Sandve Alnaes Anders Logg Kent-Andre Mardal Hans Petter Langtangen Contributors: Asmund Odegard Kristian Oelgaard Johan Hake Garth N. Wells Marie E. Rognes Johannes Ring ufc-2.3.0/CMakeLists.txt000066400000000000000000000220751226277264200150510ustar00rootroot00000000000000# Top level CMakeLists.txt file for UFC # Note that a bug in CMake < 2.8.9 might cause trouble finding Python, cf. # http://public.kitware.com/Bug/view.php?id=13216. cmake_minimum_required(VERSION 2.6) #------------------------------------------------------------------------------ # Set project name and version number project(UFC) set(UFC_VERSION_MAJOR "2") set(UFC_VERSION_MINOR "3") set(UFC_VERSION_MICRO "0") set(UFC_VERSION_STRING "${UFC_VERSION_MAJOR}.${UFC_VERSION_MINOR}.${UFC_VERSION_MICRO}") # Set special link option, see `cmake --help-policy CMP0003` if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif() # Set location of our FindFoo.cmake modules set(UFC_CMAKE_DIR "${UFC_SOURCE_DIR}/cmake" CACHE INTERNAL "") set(CMAKE_MODULE_PATH "${UFC_CMAKE_DIR}/modules") #------------------------------------------------------------------------------ # Options option(UFC_ENABLE_PYTHON "Enable Python extensions." ON) #------------------------------------------------------------------------------ # Run tests to find required packages # Find Python interpreter find_package(PythonInterp 2 QUIET) # Set variables to help find Python library that is compatible with # interpreter if (PYTHONINTERP_FOUND) # Get Python include path from Python interpretter execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import distutils.sysconfig, sys; sys.stdout.write(distutils.sysconfig.get_python_inc())" OUTPUT_VARIABLE _PYTHON_INCLUDE_PATH RESULT_VARIABLE _PYTHON_INCLUDE_RESULT) # Get Python library path from interpreter execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import os, sys, inspect; sys.stdout.write(os.path.split(os.path.split(inspect.getfile(inspect))[0])[0])" OUTPUT_VARIABLE _PYTHON_LIB_PATH RESULT_VARIABLE _PYTHON_LIB_RESULT) # Set include path, if returned by interpreter if ("${_PYTHON_INCLUDE_RESULT}" STREQUAL "0") set(PYTHON_INCLUDE_DIR ${_PYTHON_INCLUDE_PATH}) endif() # Add a search path for Python library based on output from # iterpreter if ("${_PYTHON_LIB_RESULT}" STREQUAL "0") set(CMAKE_LIBRARY_PATH ${_PYTHON_LIB_PATH}) endif() endif() # Find Python library corresponding to Python interpreter if (UFC_ENABLE_PYTHON) find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT QUIET REQUIRED) else() find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT QUIET) endif() # Find SWIG find_package(SWIG QUIET) include(UseSWIG) # Look for Boost (shared_ptr support for Python wrappers) set(Boost_ADDITIONAL_VERSIONS 1.43 1.43.0) set(BOOST_ROOT $ENV{BOOST_DIR}) find_package(Boost 1.36 QUIET) #------------------------------------------------------------------------------ # Get installation path for Python modules # Get Python module path from distutils if (PYTHONINTERP_FOUND) if (NOT DEFINED UFC_INSTALL_PYTHON_EXT_DIR) # Get path for platform-dependent Python modules (since we install # a binary libary) # Python command string to discover module install location if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(PYTHON_LIB_DISCOVER_STR "import sys, distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_lib(plat_specific=True))") else() set(PYTHON_LIB_DISCOVER_STR "import sys, distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_lib(plat_specific=True, prefix='${CMAKE_INSTALL_PREFIX}'))") endif() # Run Python to find module install path execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "${PYTHON_LIB_DISCOVER_STR}" OUTPUT_VARIABLE UFC_INSTALL_PYTHON_EXT_DIR ) set(UFC_INSTALL_PYTHON_EXT_DIR ${UFC_INSTALL_PYTHON_EXT_DIR} CACHE PATH "Python extension module installation directory.") endif() # Python command string to discover module install location if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(PYTHON_LIB_DISCOVER_STR "import sys, distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_lib(plat_specific=False))") else() set(PYTHON_LIB_DISCOVER_STR "import sys, distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_lib(plat_specific=False, prefix='${CMAKE_INSTALL_PREFIX}'))") endif() # Get path for pure Python modules if (NOT DEFINED UFC_INSTALL_PYTHON_MODULE_DIR) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "${PYTHON_LIB_DISCOVER_STR}" OUTPUT_VARIABLE UFC_INSTALL_PYTHON_MODULE_DIR ) set(UFC_INSTALL_PYTHON_MODULE_DIR ${UFC_INSTALL_PYTHON_MODULE_DIR} CACHE PATH "Python module installation directory.") endif() endif (PYTHONINTERP_FOUND) #------------------------------------------------------------------------------ # Target names and installation directories # Set UFC install sub-directories if (LIB_INSTALL_DIR) set(UFC_LIB_DIR "${LIB_INSTALL_DIR}" CACHE PATH "Library installation directory.") else() set(UFC_LIB_DIR "lib" CACHE PATH "Library installation directory.") endif() set(UFC_INCLUDE_DIR "include" CACHE PATH "C/C++ header installation directory.") set(UFC_PKGCONFIG_DIR "${UFC_LIB_DIR}/pkgconfig" CACHE PATH "pkg-config file installation directory.") set(UFC_CMAKE_CONFIG_DIR "share/ufc" CACHE PATH "CMake configuration file directory.") #------------------------------------------------------------------------------ # Install ufc.h set(UFC_H src/ufc/ufc.h src/ufc/ufc_geometry.h) install(FILES ${UFC_H} DESTINATION ${UFC_INCLUDE_DIR} COMPONENT Development) #------------------------------------------------------------------------------ # Build SWIG extension and install if (UFC_ENABLE_PYTHON AND SWIG_FOUND AND Boost_FOUND) # Check SWIG version if (${SWIG_VERSION} LESS 2.0) message(ERROR " UFC requires SWIG version 2.0 or greater. You have version ${SWIG_VERSION}. Set UFC_ENABLE_PYTHON to False or install correct SWIG version.") endif() # Default to release build (can be overridden by user) if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() # Make build directory for SWIG-generated C++ file FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/src/ufc") # In CMake 2.6 PYTHON_INCLUDE_DIRS was named PYTHON_INCLUDE_PATH if (NOT DEFINED PYTHON_INCLUDE_DIRS) set(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) endif() # Include directories include_directories(${UFC_SOURCE_DIR}/src/ufc ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}) # Set module name set(SWIG_MODULE_NAME ufc) # SWIG flags set(CMAKE_SWIG_FLAGS -module ${SWIG_MODULE_NAME} -shadow -modern -modernargs -fastdispatch -fvirtual -nosafecstrings -noproxydel -fastproxy -fastinit -fastunpack -fastquery -nobuildnone ) # SWIG sources set(SWIG_SOURCES src/ufc/ufc.i) set(SWIG_MODULE_${SWIG_MODULE_NAME}_EXTRA_DEPS ${UFC_H}) set_source_files_properties(${SWIG_SOURCES} PROPERTIES CPLUSPLUS ON) swig_add_module(${SWIG_MODULE_NAME} python ${SWIG_SOURCES}) # Is this required? swig_link_libraries(ufc ${PYTHON_LIBRARIES}) get_target_property(SWIG_MODULE_LOCATION ${SWIG_MODULE_ufc_REAL_NAME} LOCATION) message("SWIG_MODULE_LOCATION ${SWIG_MODULE_LOCATION}") # Install the swig file install(FILES src/ufc/ufc.i DESTINATION ${UFC_INCLUDE_DIR}/swig COMPONENT Development ) # Install _ufc.so and ufc.py install(FILES ${SWIG_MODULE_LOCATION} ${CMAKE_CURRENT_BINARY_DIR}/ufc.py src/ufc/__init__.py DESTINATION ${UFC_INSTALL_PYTHON_EXT_DIR}/ufc COMPONENT Development ) endif() #------------------------------------------------------------------------------ # Install Python utils (ufc_utils) install(DIRECTORY src/utils/python/ufc_utils DESTINATION ${UFC_INSTALL_PYTHON_MODULE_DIR} USE_SOURCE_PERMISSIONS COMPONENT Runtime ) #------------------------------------------------------------------------------ # Generate UFCConfig.cmake file configure_file(${UFC_CMAKE_DIR}/UFCConfig.cmake.in UFCConfig.cmake @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/UFCConfig.cmake DESTINATION ${UFC_CMAKE_CONFIG_DIR} COMPONENT Development ) #------------------------------------------------------------------------------ # Generate UFCConfigVersion.cmake file configure_file(${UFC_CMAKE_DIR}/UFCConfigVersion.cmake.in UFCConfigVersion.cmake @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/UFCConfigVersion.cmake DESTINATION ${UFC_CMAKE_CONFIG_DIR} COMPONENT Development ) #------------------------------------------------------------------------------ # Generate UseUFC.cmake file configure_file(${UFC_CMAKE_DIR}/UseUFC.cmake.in UseUFC.cmake @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/UseUFC.cmake DESTINATION ${UFC_CMAKE_CONFIG_DIR} COMPONENT Development ) #------------------------------------------------------------------------------ # Generate pkg-config config file (ufc-1.pc) configure_file(${UFC_CMAKE_DIR}/ufc-1.pc.in ufc-1.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ufc-1.pc DESTINATION ${UFC_PKGCONFIG_DIR} COMPONENT Development ) #------------------------------------------------------------------------------ ufc-2.3.0/COPYING.GPL-2000066400000000000000000000432541226277264200141260ustar00rootroot00000000000000 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 Lesser 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. ufc-2.3.0/COPYING.LGPL000066400000000000000000000167431226277264200141060ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser 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 Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ufc-2.3.0/ChangeLog000066400000000000000000000060311226277264200140550ustar00rootroot000000000000002.3.0 [2014-01-07] - Use std::vector > for topology data - Remove vertex coordinates from ufc::cell - Improve detection of compatible Python libraries - Add current swigversion to the JIT compiled extension module - Remove dofmap::max_local_dimension() - Remove cell argument from dofmap::local_dimension() 2.2.0 [2013-03-24] - Add new class ufc::point_integral - Use CMake to configure JIT compilation of forms - Generate UseUFC.cmake during configuration - Remove init_mesh(), init_cell(), init_mesh_finalize() - Remove ufc::mesh and add a vector of num_mesh_entities to global_dimension() and tabulate_dofs(). 2.1.0 [2013-01-07] - Fix bug introduced by SWIG 2.0.5, which treated uint as Python long - Add optimization SWIG flags, fixing bug lp:987657 2.0.5 [2011-12-07] - Improve configuration of libboost-math 2.0.4 [2011-11-28] - Add boost_math_tr1 to library flags when JIT compiling an extension module 2.0.3 [2011-10-26] - CMake config improvements 2.0.2 [2011-08-11] - Some tweaks of installation 2.0.1 [2011-05-16] - Make SWIG version >= 2.0 a requirement - Add possibility to set swig binary and swig path - Add missing const for map_{from,to}_reference_cell 2.0.0 [2011-02-23] - Add quadrature version of tabulate_tensor - Add finite_element::map_{from,to}_reference_cell - Add finite_element::{topological,geometric}_dimension - Add dofmap::topological_dimension - Rename num_foo_integrals --> num_foo_domains - Rename dof_map --> dofmap - Add finite_element::create - Add dofmap::create 1.4.2 [2010-09-01] - Move to CMake build system 1.4.1 [2010-07-01] - Make functions introduced in UFC 1.1 mandatory (now pure virtual) - Update templates to allow constructor arguments in form classes 1.4.0 [2010-02-01] - Changed behavior of create_foo_integral (returning 0 when integral is 0) - Bug fixes in installation 1.2.0 [2009-09-23] - Add new function ufc::dof_map::max_local_dimension() - Change ufc::dof_map::local_dimension() to ufc::dof_map::local_dimension(const ufc::cell c) 1.1.2 [2009-04-07] - Added configuration and building of python extension module to ufc_utils.build_ufc_module 1.1.1 [2009-02-20] - The extension module is now not built, if the conditions for shared_ptr are not met - Added SCons build system - The swig generated extension module will be compiled with shared_ptr support if boost is found on system and swig is of version 1.3.35 or higher - The swig generated extension module is named ufc.py and expose all ufc base classes to python - Added a swig generated extention module to ufc. UFC now depends on swig - Changed name of the python utility module from "ufc" to "ufc_utils" 1.1.0 [2008-02-18] - Add new function ufc::finite_element::evaluate_dofs - Add new function ufc::finite_element::evaluate_basis_all - Add new function ufc::finite_element::evaluate_basis_derivatives_all - Add new function ufc::dof_map::geometric_dimension - Add new function ufc::dof_map::num_entity_dofs - Add new function ufc::dof_map::tabulate_entity_dofs 1.0.0 [2007-06-17] - Release of UFC 1.0 ufc-2.3.0/LICENSE000066400000000000000000000036301226277264200133120ustar00rootroot00000000000000The header file ufc.h and the UFC Python utils are released into the public domain. ------------------------------------------------------------------------- Other files with different licenses attached: Files: doc/manual/code/Poisson.ufl doc/manual/fenicsmanual.cls Copyright: © 2004-2007 Anders Logg License: This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This file is distributed in the hope that 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. Files: doc/manual/algorithm.sty Copyright: © 1994 Peter Williams License: This style file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This style file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this style file; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Files: doc/manual/eps/insertion.eps Copyright: © 2004 artofcode LLC, Benicia, CA. License: This file was drawn with Inkscape by Anders Logg and is released into the public domain. ufc-2.3.0/README.rst000066400000000000000000000036501226277264200137760ustar00rootroot00000000000000========= UFC 2.3.0 ========= Introduction ============ UFC (Unified Form-assembly Code) is a unified framework for finite element assembly. More precisely, it defines a fixed interface for communicating low level routines (functions) for evaluating and assembling finite element variational forms. The UFC interface consists of a single header file ufc.h that specifies a C++ interface that must be implemented by code that complies with the UFC specification. Examples of form compilers that support the UFC interface are FFC and SyFi. For more information, visit the FEniCS web page at http://www.fenicsproject.org or refer to the UFC Specification and User Manual in doc/manual/ufc-user-manual.pdf in this source tree. Installation ============ To install UFC, run:: cmake . make make install This installs the header file ufc.h and a small set of Python utilities (templates) for generating UFC code. Files will be installed under the default prefix. The installation prefix may be optionally specified, for example:: cmake -DCMAKE_INSTALL_PREFIX=$HOME/local . make install Alternatively, just copy the single header file src/ufc/ufc.h into a suitable include directory. If you do not want to build and install the python extenstion module of UFC, needed by, e.g., PyDOLFIN, you can write:: cmake -DCMAKE_INSTALL_PREFIX=~/local -D UFC_ENABLE_PYTHON:BOOL=OFF . make make install For more options, it is convenient to use a CMake GUI. To use a GUI (if installed) for an out-of-source build, simply type:: mkdir build cd build cmake-gui ../ make make install AUTHORS ======= A list of authors can be found in the file AUTHORS. License ======= Details about the license can be found the file LICENSE. Feedback ======== Feedback, comments and suggestions should be sent to fenics-ufc@lists.launchpad.net For questions and bug reports, visit the UFC Launchpad page: http://www.launchpad.net/ufc ufc-2.3.0/TODO000066400000000000000000000001341226277264200127710ustar00rootroot00000000000000TODO items and suggsted features can be found at https://blueprints.launchpad.net/ufc ufc-2.3.0/cmake/000077500000000000000000000000001226277264200133635ustar00rootroot00000000000000ufc-2.3.0/cmake/UFCConfig.cmake.in000066400000000000000000000012121226277264200165310ustar00rootroot00000000000000# - UFC # CMake configuration for UFC (http:://fenicsproject.org) # # This file has been automatically generated. # FIXME: Check that naming conforms to CMake standards # Package found set(UFC_FOUND TRUE) # Include directories set(UFC_INCLUDE_DIRS "@CMAKE_INSTALL_PREFIX@/@UFC_INCLUDE_DIR@") # Python include directories set(UFC_PYTHON_INCLUDE_DIRS "@PYTHON_INCLUDE_DIRS@" "@Boost_INCLUDE_DIRS@") # Python libraries set(UFC_PYTHON_LIBRARIES "@PYTHON_LIBRARIES@") # Version set(UFC_VERSION_STRING "@UFC_VERSION_STRING@") # The location of the UseUFC.cmake file set(UFC_USE_FILE "@CMAKE_INSTALL_PREFIX@/@UFC_CMAKE_CONFIG_DIR@/UseUFC.cmake") ufc-2.3.0/cmake/UFCConfigVersion.cmake.in000066400000000000000000000014231226277264200201030ustar00rootroot00000000000000set(PACKAGE_VERSION "@UFC_VERSION_STRING@") set(PACKAGE_VERSION_MAJOR "@UFC_VERSION_MAJOR@") set(PACKAGE_VERSION_MINOR "@UFC_VERSION_MINOR@") set(PACKAGE_VERSION_PATCH "@UFC_VERSION_MICRO@") # FIXME: When should versions be defined as compatible? # This version is compatible only with matching major.minor versions. if ("${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}" VERSION_EQUAL "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}") # This version is compatible with equal or lesser patch versions. if (NOT "${PACKAGE_VERSION_PATCH}" VERSION_LESS "${PACKAGE_FIND_VERSION_PATCH}") set(PACKAGE_VERSION_COMPATIBLE 1) if ("${PACKAGE_VERSION_PATCH}" VERSION_EQUAL "${PACKAGE_FIND_VERSION_PATCH}") set(PACKAGE_VERSION_EXACT 1) endif() endif() endif() ufc-2.3.0/cmake/UseUFC.cmake.in000066400000000000000000000006061226277264200160660ustar00rootroot00000000000000# # This file sets up include directories, link directories, and # compiler settings for a project to use UFC. It should not be # included directly, but rather through the UFC_USE_FILE setting # obtained from UFCConfig.cmake. # if (NOT UFC_USE_FILE_INCLUDED) set(UFC_USE_FILE_INCLUDED 1) # Add include directories needed to use UFC include_directories(${UFC_INCLUDE_DIRS}) endif() ufc-2.3.0/cmake/ufc-1.pc.in000066400000000000000000000002041226277264200152230ustar00rootroot00000000000000Name: UFC Description: Unified Form-assembly Code Version: @UFC_VERSION_STRING@ Cflags: -I@CMAKE_INSTALL_PREFIX@/@UFC_INCLUDE_DIR@ ufc-2.3.0/doc/000077500000000000000000000000001226277264200130505ustar00rootroot00000000000000ufc-2.3.0/doc/manual/000077500000000000000000000000001226277264200143255ustar00rootroot00000000000000ufc-2.3.0/doc/manual/Makefile000066400000000000000000000010531226277264200157640ustar00rootroot00000000000000FILENAME=ufc-user-manual all: latex $(FILENAME).tex final: latex $(FILENAME).tex bibtex $(FILENAME) latex $(FILENAME).tex makeindex $(FILENAME) latex $(FILENAME) dvips -P pdf -o $(FILENAME).ps $(FILENAME).dvi ps2pdf $(FILENAME).ps $(FILENAME).pdf clean: rm -f $(FILENAME).aux rm -f $(FILENAME).idx rm -f $(FILENAME).log rm -f $(FILENAME).out rm -f $(FILENAME).toc rm -f $(FILENAME).bbl rm -f $(FILENAME).blg rm -f $(FILENAME).ilg rm -f $(FILENAME).ind purge: clean rm -f $(FILENAME).dvi rm -f $(FILENAME).ps rm -f $(FILENAME).pdf ufc-2.3.0/doc/manual/algorithm.sty000066400000000000000000000056101226277264200170560ustar00rootroot00000000000000% ALGORITHM STYLE -- Released 8 April 1996 % for LaTeX-2e % Copyright -- 1994 Peter Williams % % E-mail pwil3058@bigpond.net.au % % This style file is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2 of the License, or (at your option) any later version. % % This style file is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this style file; if not, write to the % Free Software Foundation, Inc., 59 Temple Place - Suite 330, % Boston, MA 02111-1307, USA. % \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{algorithm} \typeout{Document Style `algorithm' - floating environment} \RequirePackage{float} \RequirePackage{ifthen} \newcommand{\ALG@within}{nothing} \newboolean{ALG@within} \setboolean{ALG@within}{false} \newcommand{\ALG@floatstyle}{ruled} \newcommand{\ALG@name}{Algorithm} \newcommand{\listalgorithmname}{List of \ALG@name s} % Declare Options % first appearance \DeclareOption{plain}{ \renewcommand{\ALG@floatstyle}{plain} } \DeclareOption{ruled}{ \renewcommand{\ALG@floatstyle}{ruled} } \DeclareOption{boxed}{ \renewcommand{\ALG@floatstyle}{boxed} } % then numbering convention \DeclareOption{part}{ \renewcommand{\ALG@within}{part} \setboolean{ALG@within}{true} } \DeclareOption{chapter}{ \renewcommand{\ALG@within}{chapter} \setboolean{ALG@within}{true} } \DeclareOption{section}{ \renewcommand{\ALG@within}{section} \setboolean{ALG@within}{true} } \DeclareOption{subsection}{ \renewcommand{\ALG@within}{subsection} \setboolean{ALG@within}{true} } \DeclareOption{subsubsection}{ \renewcommand{\ALG@within}{subsubsection} \setboolean{ALG@within}{true} } \DeclareOption{nothing}{ \renewcommand{\ALG@within}{nothing} \setboolean{ALG@within}{true} } \DeclareOption*{\edef\ALG@name{\CurrentOption}} % ALGORITHM % \ProcessOptions \floatstyle{\ALG@floatstyle} \ifthenelse{\boolean{ALG@within}}{ \ifthenelse{\equal{\ALG@within}{part}} {\newfloat{algorithm}{htbp}{loa}[part]}{} \ifthenelse{\equal{\ALG@within}{chapter}} {\newfloat{algorithm}{htbp}{loa}[chapter]}{} \ifthenelse{\equal{\ALG@within}{section}} {\newfloat{algorithm}{htbp}{loa}[section]}{} \ifthenelse{\equal{\ALG@within}{subsection}} {\newfloat{algorithm}{htbp}{loa}[subsection]}{} \ifthenelse{\equal{\ALG@within}{subsubsection}} {\newfloat{algorithm}{htbp}{loa}[subsubsection]}{} \ifthenelse{\equal{\ALG@within}{nothing}} {\newfloat{algorithm}{htbp}{loa}}{} }{ \newfloat{algorithm}{htbp}{loa} } \floatname{algorithm}{\ALG@name} \newcommand{\listofalgorithms}{\listof{algorithm}{\listalgorithmname}} ufc-2.3.0/doc/manual/bibliography.bib000066400000000000000000000130161226277264200174570ustar00rootroot00000000000000@misc{www:dolfin, title = {{DOLFIN}}, author = {J. Hoffman and J. Jansson and A. Logg and G. N. Wells}, year = {2006}, note = {URL: \url{http://www.fenics.org/dolfin/}} } @misc{www:ffc, author = {A. Logg}, title = {{FFC}}, year = {2007}, note = {URL: \url{http://www.fenics.org/ffc/}}, } @misc{www:syfi, author = {M. Aln\ae{}s and K--A Mardal}, title = {{S}y{F}i}, year = {2007}, note = {URL: \url{http://www.fenics.org/syfi/}}, } @misc{www:fenics, author = {J. Hoffman and J. Jansson and C. Johnson and M. G. Knepley and R. C. Kirby and A. Logg and L. R. Scott and G. N. Wells}, title = {{FE}ni{CS}}, year = {2006}, note = {URL: \url{http://www.fenics.org/}}, } @misc{www:sundance, author = {Kevin Long}, title = {Sundance}, year = {2006}, note = {URL: \url{http://software.sandia.gov/sundance/}} } @misc{www:deal.II, author = {Wolfgang Bangerth and Ralf Hartmann and Guido Kanschat}, title = {{\tt deal.{I}{I}} {D}ifferential {E}quations {A}nalysis {L}ibrary}, year = {2006}, note = {URL: \url{http://www.dealii.org/}} } @misc{www:petsc, author = {Satish Balay and Kris Buschelman and William D. Gropp and Dinesh Kaushik and Matthew G. Knepley and Lois Curfman McInnes and Barry F. Smith and Hong Zhang}, title = {{PETS}c}, year = {2006}, note = {URL: \url{http://www.mcs.anl.gov/petsc/}} } @misc{www:trilinos, title = {Trilinos}, note = {URL: \url{http://software.sandia.gov/trilinos/}}, } @manual{www:diffpack, title = {{Diffpack}}, author = {A. M. Bruaset and H. P. Langtangen and others}, year = {2006}, note = {URL: \url{http://www.diffpack.com/}} } @article{logg:article:07, author = {R. C. Kirby and M. G. Knepley and A. Logg and L. R. Scott}, title = {Optimizing the Evaluation of Finite Element Matrices}, journal = {SIAM J. Sci. Comput.}, year = {2005}, volume = {27}, number = {3}, pages = {741--758}, issn = {1064-8275} } @article{logg:article:09, author = {R. C. Kirby and A. Logg and L. R. Scott and A. R. Terrel}, title = {Topological Optimization of the Evaluation of Finite Element Ma trices}, journal = {{SIAM} J. Sci. Comput.}, year = {2006}, volume = {28}, number = {1}, pages = {224--240}, issn = {1064-8275} } @article{logg:article:10, author = "R. C. Kirby and A. Logg", title = "A Compiler for Variational Forms", journal = "{ACM} Transactions on Mathematical Software", volume = "32", number = "3", pages = "417--444", year = "2006", accepted = "13 November 2005", abstract = "As a key step towards a complete automation of the finite elem ent method, we present a new algorithm for automatic and efficient evaluati on of multilinear variational forms. The algorithm has been implement ed in the form of a compiler, the FEniCS Form Compiler FFC. We present be nchmark results for a series of standard variational forms, including t he incompressible Navier-Stokes equations and linear elasticity. T he speedup compared to the standard quadrature-based approach is impressiv e; in some cases the speedup is as large as a factor 1000.", issn = {0098-3500}, } @article{logg:article:11, author = "R. C. Kirby and A. Logg", title = "Efficient Compilation of a Class of Variational Forms", journal = "{ACM} Transactions on Mathematical Software", volume = "33", number = "3", year = "2007", accepted = "31 August 2006", abstract = "We investigate the compilation of general multilinear variatio nal forms over affines simplices and prove a representation theorem for the representation of the element tensor (element stiffness mat rix) as the contraction of a constant reference tensor and a geometr y tensor that accounts for geometry and variable coefficients. Ba sed on this representation theorem, we design an algorithm for effi cient pretabulation of the reference tensor. The new algorithm has b een implemented in the FEniCS Form Compiler~(FFC) and improves on a previous loop-based implementation by several orders of magnitu de, thus shortening compile-times and development cycles for users of FFC.", year = "2007", issn = {0098-3500}, } @book{ZieTay67, author = {O. C. Zienkiewicz and R. L. Taylor and J. Z. Zhu}, title = {The Finite Element Method --- Its Basis and Fundamentals, 6th e dition}, publisher = {Elsevier}, year = {2005, first published in 1967}, } @book{Hug87, author = {T. J. R. Hughes}, title = {The Finite Element Method: Linear Static and Dynamic Finite Ele ment Analysis}, publisher = {Prentice-Hall}, year = {1987}, } @book{Lan99, author = {H. P. Langtangen}, title = {Computational Partial Differential Equations -- Numerical Metho ds and Diffpack Programming}, publisher = {Springer}, year = {1999}, series = {Lecture Notes in Computational Science and Engineering}, } @book{Cia78, author = {P. G. Ciarlet}, title = {The Finite Element Method for Elliptic Problems}, publisher = {North-Holland, Amsterdam, New York, Oxford}, year = {1978}, } ufc-2.3.0/doc/manual/chapters/000077500000000000000000000000001226277264200161365ustar00rootroot00000000000000ufc-2.3.0/doc/manual/chapters/assembly.tex000066400000000000000000000375241226277264200205120ustar00rootroot00000000000000\chapter{Finite element assembly} \label{sec:assembly} \newtheorem{example}{\small{\sc{Example}}}[section] In this section, we present a general algorithm for assembly of finite element variational forms and define the concepts that the UFC interface is based on. \section{Finite Element Discretization} \label{sec:fem} \subsection{The Finite Element} \index{finite element} A finite element is mathematically defined as a triplet consisting of a polygon, a polynomial function space, and a set of linear functionals, see~\cite{Cia78}. Given that the dimension of the function space and the number of the (linearly independent) linear functionals are equal, the finite element is uniquely defined. Hence, we will refer to a finite element as a collection of \begin{itemize} \item a polygon $K$, \item a polynomial space $\mathcal{P}_K$ on $K$, \item a set of linearly independent linear functionals, the \emph{degrees of freedom}, $L_i : \mathcal{P}_K \rightarrow \R, \, i = 1, 2, \ldots, n$. \end{itemize} \subsection{Variational Forms} \index{variational form} Consider the weighted Poisson problem $- \nabla \cdot (w \nabla u) = f$ with Dirichlet boundary conditions on a domain $\Omega \subset \R^d$. Multiplying by a test function $v \in V_h$ and integrating by parts, one obtains the variational problem \begin{equation} \label{eq:weightedpoisson} \int_{\Omega} w \nabla v \cdot \nabla u \dx = \int_{\Omega} v f \dx \quad \forall v \in V_h, \end{equation} for $u \in V_h$. If $w, f \in W_h$ for some discrete finite element space $W_h$ (which may be different from $V_h$), we may thus write~(\ref{eq:weightedpoisson}) as \begin{equation} a(v, u; w) = L(v; f) \quad \forall v \in V_h, \end{equation} where the trilinear form $a : V_h \times V_h \times W_h \rightarrow \R$ is given by \begin{equation} a(v, u; w) = \int_{\Omega} w \nabla v \cdot \nabla u \dx \end{equation} and the bilinear form $L : V_h \times W_h \rightarrow R$ is given by \begin{equation} L(v; f) = \int_{\Omega} v f \dx. \end{equation} Note here that $a$ is \emph{bilinear} for any given fixed $w \in W_h$ and $L$ is \emph{linear} for any given fixed $f \in W_h$. In general, we shall be concerned with the discretization of finite element variational forms of general arity~$r + n > 0$, \begin{equation} \label{eq:variationalform} a : V_h^1 \times V_h^2 \times \cdots \times V_h^r \times W_h^1 \times W_h^2 \times \cdots \times W_h^n \rightarrow \R, \end{equation} defined on the product space $V_h^1 \times V_h^2 \times \cdots \times V_h^r \times W_h^1 \times W_h^2 \times \cdots \times W_h^n$ of two sets $\{V_h^j\}_{j=1}^r, \{W_h^j\}_{j=1}^n$ of discrete finite element function spaces on $\Omega$. We refer to $(v_1, v_2, \ldots, v_r) \in V_h^1 \times V_h^2 \times \cdots \times V_h^r$ as \emph{primary arguments}, and to $(w_1, w_2, \ldots, w_n) \in W_h^1 \times W_h^2 \times \cdots \times W_h^n$ as \emph{coefficients} and write \begin{equation} a = a(v_1, \ldots, v_r; w_1, \ldots, w_n). \label{eq:gen_form} \end{equation} In the simplest case, all function spaces are equal but there are many important examples, such as mixed methods, where the arguments come from different function spaces. \subsection{Discretization} \label{sec:Discretization} To discretize the form $a$, we introduce bases $\{\phi_i^1\}_{i=1}^{N^1}, \{\phi_i^2\}_{i=1}^{N^2}, \ldots, \{\phi_i^r\}_{i=1}^{N^r}$ for the function spaces $V_h^1, V_h^2, \ldots, V_h^r$ respectively and let $i = (i_1, i_2, \ldots, i_r)$ be a multiindex of length $|i| = r$. The form $a$ then defines a rank~$r$ tensor given by \begin{equation} \label{eq:tensor} A_i = a(\phi_{i_1}^1, \phi_{i_2}^2, \ldots, \phi_{i_r}^r; w_1, w_2, \ldots, w_n) \quad \forall i \in \mathcal{I}, \end{equation} where $\mathcal{I}$ is the index set \begin{equation} \begin{split} & \mathcal{I} = \prod_{j=1}^r[1,|V^j_h|] = \\ & \{(1,1,\ldots,1), (1,1,\ldots,2), \ldots, (N^1,N^2,\ldots,N^r)\}. \end{split} \end{equation} We refer to the tensor~$A$ as the \emph{discrete operator} generated by the form~$a$ and the particular choice of basis functions. For any given form of arity~$r + n$, the tensor~$A$ is a (typically sparse) tensor of rank~$r$ and dimension $|V_h^1| \times |V_h^2| \times \ldots \times |V_h^r| = N^1 \times N^2 \times \ldots \times N^r$. \index{global tensor} Typically, the rank $r$ is 0, 1, or 2. When $r = 0$, the tensor $A$ is a scalar (a tensor of rank zero), when $r = 1$, the tensor $A$ is a vector (the ``load vector'') and when $r = 2$, the tensor $A$ is a matrix (the ``stiffness matrix''). Forms of higher arity also appear, though they are rarely assembled as a higher-dimensional sparse tensor. Note here that we consider the functions $w_1, w_2, \ldots, w_n$ as fixed in the sense that the discrete operator~$A$ is computed for a given set of functions, which we refer to as \emph{coefficients}. As an example, consider again the variational problem~(\ref{eq:weightedpoisson}) for the weighted Poisson's equation. For the trilinear form~$a$, the rank is $r = 2$ and the number of coefficients is $n = 1$, while for the linear form~$L$, the rank is $r = 1$ and the number of coefficients is $n = 1$. We may also choose to directly compute the \emph{action} of the form $a$ obtained by assembling a vector from the form \begin{equation} a(v_1; w_1, w2) = \int_{\Omega} w_1 \nabla v_1 \cdot \nabla w_2 \dx, \end{equation} where now $r = 1$ and $n = 2$. We list below a few other examples to illustrate the notation. \begin{example} \label{example:div} Our first example is related to the divergence constraint in fluid flow. Let the form~$a$ be given by \begin{equation} a(q, u) = \int_{\Omega} q \nabla \cdot u \dx, \quad q\in V_h^1, \quad u\in V_h^2, \end{equation} where $V_h^1$ is a space of scalar-valued functions and where $V_h^2$ is a space of vector-valued functions. The form $a : V_h^1 \times V_h^2 \rightarrow \R$ has two primary arguments and thus $r = 2$. Furthermore, the form does not depend on any coefficients and thus $n=0$. \end{example} \begin{example} \label{example:linearconv} Another common form in fluid flow (with variable density) is \begin{equation} a(v,u;w,\varrho) = \int_{\Omega} v \, \varrho \, w \cdot \nabla u \dx. \end{equation} Here, $v\in V_h^1,\ u \in V_h^2,\ w\in W_h^1, \ \varrho \in W_h^2$, where $V_h^1$, $V_h^2$, and $W_h^1$ are spaces of vector-valued functions, while $W_h^2$ is a space of scalar-valued functions. The form takes four arguments, where two of the arguments are coefficients, \begin{equation} a : V_h^1 \times V_h^2 \times W_h^1 \times W_h^2 \rightarrow \R. \end{equation} Hence, $r=2$ and $n=2$. \end{example} \begin{example} The $H^1(\Omega)$ norm of the error $e = u - u_h$ squared is \begin{equation} a(;u, u_h) = \int_{\Omega} (u - u_h)^2 + |\nabla (u - u_h)|^2 \dx. \end{equation} The form takes two arguments and both are coefficients, \begin{equation} a : W_h^1 \times W_h^2 \rightarrow \R. \end{equation} Hence, $r=0$ and $n=2$. \end{example} \section{Finite Element Assembly} \index{assembly} The standard algorithm for computing the global sparse tensor~$A$ is known as \emph{assembly}, see~\cite{ZieTay67,Hug87}. By this algorithm, the tensor~$A$ may be computed by assembling (summing) the contributions from the local entities of a finite element mesh. To express this algorithm for assembly of the global sparse tensor~$A$ for a general finite element variational form of arity~$r$, we introduce the following notation and assumptions. Let $\mathcal{T} = \{K\}$ be a set of disjoint \emph{cells} (a triangulation) partitioning the domain $\Omega = \cup_{K\in\mathcal{T}} K$. Further, let $\partial_e \mathcal{T}$ denote the set of \emph{exterior facets} (the set of cell facets incident with the boundary $\partial \Omega$), and let $\partial_i \mathcal{T}$ denote the set of $\emph{interior facets}$ (the set of cell facets non-incident with the boundary $\partial \Omega$). For each discrete function space $V_h^j, \, j=1,2,\ldots,r$, we assume that the global basis~$\{\phi_i^j\}_{i=1}^{N^j}$ is obtained by patching together local function spaces $\mathcal{P}_K^j$ on each cell~$K$ as determined by a local-to-global mapping. We shall further assume that the variational form~(\ref{eq:variationalform}) may be expressed as a sum of integrals over the cells~$\mathcal{T}$, the exterior facets~$\partial_e \mathcal{T}$ and the interior facets~$\partial_i \mathcal{T}$. We shall allow integrals expressed on disjoint subsets $\mathcal{T} = \cup_{k=1}^{n_c} \mathcal{T}_k$, $\partial_e \mathcal{T} = \cup_{k=1}^{n_e} \partial_e \mathcal{T}_k$ and $\partial_i \mathcal{T} = \cup_{k=1}^{n_i} \partial_i \mathcal{T}_k$ respectively. We thus assume that the form $a$ is given by \begin{equation} \begin{split} & a(v_1, \ldots, v_r; w_1, \ldots, w_n) = \\ &\ \ \ \sum_{k=1}^{n_c} \sum_{K\in\mathcal{T}_k} \int_{K} I^c_k(v_1, \ldots, v_r; w_1, \ldots w_n) \dx \\ &+ \sum_{k=1}^{n_e} \sum_{S\in\partial_e\mathcal{T}_k} \int_{S} I^e_k(v_1, \ldots, v_r; w_1, \ldots, w_n) \ds \\ &+ \sum_{k=1}^{n_i} \sum_{S\in\partial_i\mathcal{T}_k} \int_{S} I^i_k(v_1, \ldots, v_r; w_1, \ldots, w_n) \ds. \end{split} \label{eq:form_integrals} \end{equation} We refer to an integral over a cell~$K$ as a \emph{cell integral}, an integral over an exterior facet~$S$ as an \emph{exterior facet integral} (typically used to implement Neumann and Robin type boundary conditions), and to an integral over an interior facet~$S$ as an \emph{interior facet integral} (typically used in discontinuous Galerkin methods). For simplicity, we consider here initially assembly of the global sparse tensor~$A$ corresponding to a form~$a$ given by a single integral over all cells $\mathcal{T}$, and later extend to the general case where we must also account for contributions from several cell integrals, interior facet integrals and exterior facet integrals. We thus consider the form \begin{equation} \begin{split} &a(v_1, \ldots, v_r; w_1, \ldots, w_n) = \\ & \ \ \ \sum_{K\in\mathcal{T}} \int_K I^c(v_1, \ldots, v_r; w_1, \ldots, w_n) \dx, \end{split} \end{equation} for which the global sparse tensor~$A$ is given by \begin{equation} A_i = \sum_{K\in\mathcal{T}} \int_K I^c(\phi^1_{i_1}, \ldots, \phi^r_{i_r}; w_1, \ldots, w_n) \dx. \end{equation} To see how to compute the tensor $A$ by summing the local contributions from each cell~$K$, we let $n^j_K = |\mathcal{P}^j_K|$ denote the dimension of the local finite element space on $K$ for the $j$th primary argument $v_j \in V_h^j$ for $j = 1,2,\ldots,r$. Furthermore, let \begin{equation} \iota_K^j : [1,n_K^j] \rightarrow [1,N^j] \label{eq:iota_K} \end{equation} denote the local-to-global mapping for~$V_h^j$, that is, on any given $K\in\mathcal{T}$, the mapping $\iota_K^j$ maps the number of a local degree of freedom (or, equivalently, local basis function) to the number of the corresponding global degree of freedom (or, equivalently, global basis function). We then define for each $K \in \mathcal{T}$ the collective local-to-global mapping $\iota_K : \mathcal{I}_K \rightarrow \mathcal{I}$ by \begin{equation} \iota_K(i) = (\iota_K^1(i_1),\iota_K^2(i_2),\ldots,\iota_K^r(i_r)) \quad \forall i \in \mathcal{I}_K, \end{equation} where $\mathcal{I}_K$ is the index set \begin{equation} \begin{split} & \mathcal{I}_K = \prod_{j=1}^r[1,|\mathcal{P}_K^j|] \\ & = \{(1,1,\ldots,1), (1,1,\ldots,2), \ldots, (n_K^1,n_K^2,\ldots,n_K^r)\}. \end{split} \end{equation} Furthermore, for each $V_h^j$ we let $\{\phi^{K,j}_i\}_{i=1}^{n_K^j}$ denote the restriction to an element $K$ of the subset of the basis $\{\phi_i^j\}_{i=1}^{N^j} \subset \mathcal{P}_K^j$ of $V_h^j$ supported on $K$. We may now compute~$A$ by summing the contributions from the local cells, \begin{equation} \begin{split} A_i &= \sum_{K\in\mathcal{T}_i} \int_K I^c(\phi_{i_1}^1, \ldots, \phi_{i_r}^r; w_1, \ldots, w_n) \dx \\ &= \sum_{K\in\mathcal{T}_i} \int_K I^c(\phi_{(\iota_K^1)^{-1}(i_1)}^{K,1}, \ldots, \phi_{(\iota_K^r)^{-1}(i_r)}^{K,r}; w_1, \ldots, w_n) \dx \\ &= \sum_{K\in\mathcal{T}_i} A^K_{\iota_K^{-1}(i)}, \end{split} \end{equation} where $A^K$ is the local \emph{cell tensor} on cell $K$ (the ``element stiffness matrix''), given by \begin{equation} A^K_i = \int_K I^c(\phi_{i_1}^{K,1}, \ldots, \phi_{i_r}^{K,r}; w_1, \ldots, w_n) \dx, \\ \end{equation} and where $\mathcal{T}_i$ denotes the set of cells on which all basis functions $\phi_{i_1}^1, \phi_{i_2}^2, \ldots, \phi_{i_r}^r$ are supported. Similarly, we may sum the local contributions from the exterior and interior facets in the form of local \emph{exterior facet tensors} and \emph{interior facet tensors}. \index{cell tensor} \index{exterior facet tensor} \index{interior facet tensor} \begin{figure}[htbp] \begin{center} \psfrag{i0}{\hspace{-0.5cm}$\iota_K^1(1)$} \psfrag{i1}{\hspace{-0.5cm}$\iota_K^1(2)$} \psfrag{i2}{\hspace{-0.5cm}$\iota_K^1(3)$} \psfrag{j0}{\hspace{-0.3cm}$\iota_K^2(1)$} \psfrag{j1}{\hspace{-0.5cm}$\iota_K^2(2)$} \psfrag{j2}{\hspace{-0.1cm}$\iota_K^2(3)$} \psfrag{A21}{$A^K_{32}$} \psfrag{1}{$1$} \psfrag{2}{$2$} \psfrag{3}{$3$} \includegraphics[height=3in]{eps/insertion.eps} \caption{Adding the entries of a cell tensor~$A^K$ to the global tensor~$A$ using the local-to-global mapping $\iota_K$, illustrated here for a rank two tensor (a matrix).} \label{fig:insertion} \end{center} \end{figure} In Algorithm~\ref{alg:assembly}, we present a general algorithm for assembling the contributions from the local cell, exterior facet and interior facet tensors into a global sparse tensor. In all cases, we iterate over all entities (cells, exterior or interior facets), compute the local cell tensor $A^K$ (or exterior/interior facet tensor $A^S$) and add it to the global sparse tensor as determined by the local-to-global mapping, see~Figure~\ref{fig:insertion}. \begin{algorithm} \footnotesize $A = 0$ \\ (i) \emph{Assemble contributions from all cells} \\ \textbf{for each} $K \in \mathcal{T}$ \\ \\ \tab \textbf{for} $j = 1,2,\ldots,r$: \\ \tab\tab Tabulate the local-to-global mapping $\iota_K^j$ \\ \\ \tab \textbf{for} $j = 1,2,\ldots,n$: \\ \tab\tab Extract the values of $w_j$ on $K$ \\ \\ \tab Take $0 \leq k \leq n_c$ such that $K \in \mathcal{T}_k$ \\ \tab Tabulate the cell tensor $A^K$ for $I^c_k$ \\ \tab Add $A^K_i$ to $A_{\iota_K^1(i_1), \iota_K^2(i_2), \ldots, \iota_K^r(i_r)}$ for $i\in I_K$ \\ \\ (ii) \emph{Assemble contributions from all exterior facets} \\ \textbf{for each} $S \in \partial_e\mathcal{T}$ \\ \\ \tab \textbf{for} $j = 1,2,\ldots,r$: \\ \tab\tab Tabulate the local-to-global mapping $\iota_{K(S)}^j$ \\ \\ \tab \textbf{for} $j = 1,2,\ldots,n$: \\ \tab\tab Extract the values of $w_j$ on $K(S)$ \\ \\ \tab Take $0 \leq k \leq n_e$ such that $S \in \partial_e \mathcal{T}_k$ \\ \tab Tabulate the exterior facet tensor $A^S$ for $I^e_k$ \\ \tab Add $A^S_i$ to $A_{\iota_{K(S)}^1(i_1), \iota_{K(S)}^2(i_2), \ldots, \iota_{K(S)}^r(i_r)}$ for $i\in I_{K(S)}$ \\ \\ \\ (iii) \emph{Assemble contributions from all interior facets} \\ \textbf{for each} $S \in \partial_i\mathcal{T}$ \\ \\ \tab \textbf{for} $j = 1,2,\ldots,r$: \\ \tab\tab Tabulate the local-to-global mapping $\iota_{K(S)}^j$ \\ \\ \tab \textbf{for} $j = 1,2,\ldots,n$: \\ \tab\tab Extract the values of $w_j$ on $K(S)$ \\ \\ \tab Take $0 \leq k \leq n_i$ such that $S \in \partial_i \mathcal{T}_k$ \\ \tab Tabulate the interior facet tensor $A^S$ for $I^i_k$ \\ \tab Add $A^S_i$ to $A_{\iota_{K(S)}^1(i_1), \iota_{K(S)}^2(i_2), \ldots, \iota_{K(S)}^r(i_r)}$ for $i\in I_{K(S)}$ \\ \caption{Assembling the global tensor~$A$ from the local contributions on all cells, exterior and interior facets. For assembly over exterior facets, $K(S)$ refers to the cell $K\in\mathcal{T}$ incident to the exterior facet~$S$, and for assembly over interior facets, $K(S)$ refers to the ``macro cell'' consisting of the pair of cells $K^+$ and $K^-$ incident to the interior facet~$S$.} \label{alg:assembly} \end{algorithm} \normalsize ufc-2.3.0/doc/manual/chapters/assembly_cpp.tex000066400000000000000000000063041226277264200213440ustar00rootroot00000000000000\chapter{A basic UFC-based assembler} \label{app:assembly} Below, we include a sketch of a UFC-based implementation of the assembly of the global tensor~$A$ by summing the local contributions from all cells. The contributions from all exterior and interior facets may be computed similarly. The implementation is incomplete and system specific details such as interaction with mesh and linear algebra libraries have been omitted.\footnote{For an example of a complete implementation of a UFC-based assembler, we refer to the source code of DOLFIN~\cite{www:dolfin}, in particular class \texttt{Assembler} as implemented in \texttt{Assembler.cpp}.} \scriptsize \begin{code} void assemble(..., ufc::form& form, ...) { ... // Initialize mesh data structure ufc::mesh mesh; mesh.num_entities = new unsigned int[...]; ... // Initialize cell data structure ufc::cell cell; cell.entity_indices = new unsigned int[...]; cell.coordinates = new double[...]; ... // Create cell integrals ufc::cell_integral** cell_integrals; cell_integrals = new ufc::cell_integral*[form.num_cell_domains()]; for (unsigned int i = 0; i < form.num_cell_domains(); i++) cell_integrals[i] = form.create_cell_integral(i); // Create dofmaps ufc::dofmaps** dofmaps; dofmaps = new ufc::dofmap*[form.rank() + form.num_coefficients()]; for (unsigned int i = 0; i < form.rank() + form.num_coefficients(); i++) { dofmaps[i] = form.create_dofmap(i); // Initialize dofmap if (dofmaps[i]->init_mesh(mesh)) { // Iterate over cells for (...) { // Update cell data structure to current cell cell.entity_indices[...] = ... cell.coordinates[...] = ... ... // Initialize dofmap for cell dofmaps[i]->init_cell(mesh, cell); } dofmap.init_cell_finalize(); } } // Initialize array of values for the cell tensor unsigned int size = 1; for (unsigned int i = 0; i < form.rank(); i++) size *= dofmaps[i]->max_local_dimension(); double* AK = new double[size]; // Initialize array of local to global dofmaps unsigned int** dofs = new unsigned int*[form.rank()]; for (unsigned int i = 0; i < form.rank(); i++) dofs[i] = new unsigned int[dofmaps[i]->max_local_dimension()]; // Initialize array of coefficient values double** w = new double*[form.num_coefficients()]; for (unsigned int i = 0; i < form.num_coefficients(); i++) w[i] = new double[dofmaps[form.rank() + i]->max_local_dimension()]; // Iterate over cells for (...) { // Get number of subdomain for current cell const unsigned int sub_domain = ... // Update cell data structure to current cell cell.entity_indices[...] = ... cell.coordinates[...] = ... ... // Interpolate coefficients (library specific so omitted here) ... // Tabulate dofs for each dimension for (unsigned int i = 0; i < ufc.form.rank(); i++) dofmaps[i]->tabulate_dofs(dofs[i], mesh, cell); // Tabulate cell tensor cell_integrals[sub_domain]->tabulate_tensor(AK, w, cell); // Add entries to global tensor (library specific so omitted here) ... } // Delete data structures delete [] mesh.num_entities; ... } \end{code} \normalsize ufc-2.3.0/doc/manual/chapters/examples.tex000066400000000000000000000055661226277264200205120ustar00rootroot00000000000000\chapter{Complete UFC code for Poisson's equation} \index{Poisson's equation} \index{example code} In this section, a simple example is given of UFC code generated by the form compilers FFC~\cite{www:ffc,logg:article:07,logg:article:09,logg:article:10,logg:article:11} and SyFi~\cite{www:syfi} for Poisson's equation. The code presented below is generated for the bilinear form of Poisson's equation for standard continuous piecewise linear Lagrange finite elements on a two-dimensional domain $\Omega$, \begin{equation} a(v, u) = \int_{\Omega} \nabla v \cdot \nabla u \dx. \end{equation} Although FFC and SyFi are two different form compilers, with very different approaches to code generation, both generate code that conforms to the UFC specification and may thus be used interchangeably within any UFC-based system. In the generated code, we have omitted the two functions \texttt{evaluate\_basis} and \texttt{evaluate\_basis\_derivatives}\footnotemark{} to save space. \footnotetext{For FFC, this may be done by using the compiler flags \texttt{-fno-evaluate\_basis} and \texttt{-fno-evaluate\_basis\_derivatives}.} \section{Code generated by FFC} \index{FFC} \scriptsize \VerbatimInput[frame=single,rulecolor=\color{blue}]{code/poisson_ffc.h} \normalsize \section{Code generated by SyFi} \index{SyFi} In the following we list the complete code for the finite element, the dofmap and the variational form for computing a stiffness matrix based on linear Lagrangian elements in 2D. The code below is generated for the assembler in PyCC and it therefore includes some PyCC files, since the option \texttt{SFC.options.include\_from = "pycc"} was used during the code generation. If PyCC is not present, the option \texttt{SFC.options.include\_from = "syfi"} can be used, and this will result in some additional files that define the numbering scheme. \subsection{Header file for linear Lagrange element in 2D} \scriptsize \VerbatimInput[frame=single,rulecolor=\color{blue}]{code/stiffness_syfi/fe_Lagrange_1_2D.h} \normalsize \subsection{Source file for linear Lagrange element in 2D} \scriptsize \VerbatimInput[frame=single,rulecolor=\color{blue}]{code/stiffness_syfi/fe_Lagrange_1_2D.cpp} \normalsize \subsection{Header file for the dofmap} \scriptsize \VerbatimInput[frame=single,rulecolor=\color{blue}]{code/stiffness_syfi/dof_map_Lagrange_1_2D.h} \normalsize \subsection{Source file for the dofmap} \scriptsize \VerbatimInput[frame=single,rulecolor=\color{blue}]{code/stiffness_syfi/dof_map_Lagrange_1_2D.cpp} \normalsize \subsection{Header file for the stiffness matrix form} \scriptsize \VerbatimInput[frame=single,rulecolor=\color{blue}]{code/stiffness_syfi/form__stiffness_form__Lagrange_1_2D.h} \normalsize \subsection{Source file for the stiffness matrix form} \scriptsize \VerbatimInput[frame=single,rulecolor=\color{blue}]{code/stiffness_syfi/form__stiffness_form__Lagrange_1_2D.cpp} \normalsize ufc-2.3.0/doc/manual/chapters/installation.tex000066400000000000000000000023111226277264200213560ustar00rootroot00000000000000\chapter{Installation} \label{app:installation} \index{installation} The \ufc{} package consists of two parts, the main part being a single header file called \texttt{ufc.h}. In addition, a set of Python utilities to simplify the generation of \ufc{} code is provided. Questions, bug reports and patches concerning the installation should be directed to the \ufc{} mailing list at the address \begin{code} fenics@lists.launchpad.net \end{code} \section{Installing \ufc{}} To install UFC, simply run \begin{code} scons sudo scons install \end{code} This installs the header file ufc.h and a small set of Python utilities (templates) for generating UFC code. Files will be installed under the default prefix. The installation prefix may be optionally specified, for example \begin{code} scons install prefix=~/local \end{code} Alternatively, just copy the single header file \texttt{src/ufc/ufc.h} into a suitable include directory. If you do not want to build and install the python extenstion module of \ufc{}, needed by, e.g., PyDOLFIN, you can write \begin{code} sudo enablePyUFC=No sudo cons install \end{code} Help with available options and default arguments can be viewed by \begin{code} scons -h \end{code} ufc-2.3.0/doc/manual/chapters/interface.tex000066400000000000000000001322161226277264200206250ustar00rootroot00000000000000\chapter{Interface specification} \label{sec:interface} \index{interface} \section{A short remark on design} \index{design} UFC is organized as a minimalistic set of abstract C++ classes representing low-level abstractions of the finite element method. The functions in these classes are mainly of two types: (i) functions returning dimensions, which are typically used to allocate an array, and (ii) functions that fill an array with values. It is considered the assembly routine's responsibility to allocate and deallocate arrays of proper size. Consider for example the function for evaluating the $i$th basis function in the class \texttt{ufc::finite\_element}: \begin{code} virtual void evaluate_basis(unsigned int i, double* values, const double* coordinates, const cell& c) const = 0; \end{code} This function assumes that the array \texttt{values} has the correct size, which may be obtained by calling the functions \texttt{value\_rank} and \texttt{value\_dimension} as described in detail below. Thus, the UFC interface is a low-level interface that should be simple to integrate into an existing C++ finite element code, but which is probably not suitable to be exposed as part of an end-user interface. The UFC interface is defined by a single header file \texttt{ufc.h} which defines the central interface class \texttt{ufc::form} and a small set of auxiliary interface classes. In addition, a pair of data structures \texttt{ufc::mesh} and \texttt{ufc::cell} are defined and used for passing data to the interface functions. All functions defined by the UFC interface are \emph{pure virtual}, meaning that all these functions must be overloaded in each implementation of the classes. All but two functions (\texttt{init\_mesh} and \texttt{init\_cell}) are \texttt{const}, meaning that calling these \texttt{const} functions will leave the UFC objects unchanged. Input argument (pointers) are always \texttt{const}, while output arguments (pointers) are always non-\texttt{const}. \index{ufc.h} The interface is presented below in the same order as it is defined in the header file \texttt{ufc.h}. Thus, the interface is presented bottom-up, starting with the definition of basic data structures and ending with the definition of the main \texttt{ufc::form} interface class. \section{Cell shapes} \index{Cell shapes} \index{\texttt{interval}} \index{\texttt{triangle}} \index{\texttt{quadrilateral}} \index{\texttt{tetrahedron}} \index{\texttt{hexahedron}} \begin{code} enum shape {interval, triangle, quadrilateral, tetrahedron, hexahedron}; \end{code} This enumeration includes all cell shapes that are covered by the UFC specification, see Chapter~\ref{sec:referencecells}. \section{The class \texttt{ufc::mesh}} \index{\texttt{ufc::mesh}} The class \texttt{ufc::mesh} defines a data structure containing basic information about an unstructured mesh. It is used for passing a minimal amount of information about the global mesh to UFC functions. \subsection{The integer \texttt{topological\_dimension}} \begin{code} unsigned int topological_dimension; \end{code} The unsigned integer \texttt{topological\_dimension} holds the topological dimension of the mesh, that is, the topological dimension of the cells of the mesh. For the supported cell shapes defined above, the topological dimensions are as follows: \texttt{interval} has dimension one, \texttt{triangle} and \texttt{quadri\-lateral} have dimension two, and \texttt{tetrahedron} and \texttt{hexahedron} have dimension three. \subsection{The integer \texttt{geometric\_dimension}} \begin{code} unsigned int geometric_dimension; \end{code} The unsigned integer \texttt{geometric\_dimension} holds the geometric dimension of the mesh, that is, the dimension of the coordinates of the mesh vertices. Often, the geometric dimension is equal to the topological dimension, but they may differ. For example, one may have a topologically two-dimensional mesh embedded in three-dimensional space. \subsection{The array \texttt{num\_entities}} \begin{code} unsigned int* num_entities; \end{code} The array \texttt{num\_entities} should contain the number of entities within each topological dimension of the mesh (see Chapter~\ref{sec:referencecells}). The size of the array should be equal to the topological dimension of the mesh plus one. Thus, for a mesh of tetrahedral cells, \texttt{num\_entities[0]} should contain the number of vertices, \texttt{num\_entities[1]} should contain the number of edges (if they are needed, see \texttt{ufc::dofmap::needs\_mesh\_entities} below), \texttt{num\_en\-tities[2]} should contain the number of faces, and \texttt{num\_entities[3]} should contain the number of volumes. If \texttt{d} is the topological dimension of the mesh, \texttt{num\_entities[d]} should contain the number of cells or elements. \section{The class \texttt{ufc::cell}} \index{\texttt{ufc::cell}} The class \texttt{ufc::cell} defines the data structure for a cell in a mesh. Its intended use is not as a building block in a mesh data structure, but merely as a view of specific data for a single cell. It is used to pass cell data to UFC functions with a minimal amount of assumptions on how the computational mesh is represented and stored. \subsection{The enum variable \texttt{cell\_shape}} \begin{code} shape cell_shape; \end{code} The variable \texttt{cell\_shape} should be set to the corresponding \texttt{ufc::shape} for the cell. \subsection{The integer \texttt{topological\_dimension}} \begin{code} unsigned int topological_dimension; \end{code} The integer \texttt{topological\_dimension} should be set to the topological dimension of the cell (see \texttt{ufc::mesh} above). \subsection{The integer \texttt{geometric\_dimension}} \begin{code} unsigned int geometric_dimension; \end{code} The integer \texttt{geometric\_dimension} should be set to the geometric dimension of the cell (see \texttt{ufc::mesh} above). \subsection{The array \texttt{entity\_indices}} \begin{code} unsigned int** entity_indices; \end{code} The array \texttt{entity\_indices} should contain the global indices for all entities of the cell (see Chapter~\ref{sec:referencecells}). The length of the array \texttt{entity\_indices} should be equal to the value of the variable \texttt{topological\_dimension} plus one. Thus, \texttt{entity\_indices[0]} should be an array containing the global indices of all the vertices of the cell, \texttt{entity\_indices[1]} should be an array containing the global indices of all the edges of the cell, etc. The sizes of these arrays are implicitly defined by the cell type. Note that the entity indices are not always needed for all entities of the cell. Which entities are required is specified by the \texttt{ufc::dofmap} class (see \texttt{ufc::dofmap::needs\_mesh\_entities} below). \subsection{The array \texttt{coordinates}} \begin{code} double** coordinates; \end{code} The array \texttt{coordinates} should contain the global coordinates for all vertices of the cell and thus its length should be equal to number of vertices of the cell. The length of the array \texttt{coordinates[0]} should be equal to the value of the variable \texttt{geometric\_dimension} and it should contain the $x$, $y$, \ldots coordinates of the first vertex etc. \subsection{The integer \texttt{index}} Introduced in UFC version 2.0. \begin{code} unsigned int index; \end{code} The integer \texttt{index} should contain the global index for the cell. This is a short-cut for \texttt{entity\_indices[topological\_dimension][0]}. \subsection{The integer \texttt{local\_facet}} Introduced in UFC version 2.0. \begin{code} int local_facet; \end{code} The integer \texttt{local\_facet} can be used during callbacks to the \texttt{evaluate} function of \texttt{ufc::function} to specify the local index of a facet (relative to the cell) on which the function is being evaluated. In all other cases, this variable should be set to \texttt{-1}. \subsection{The integer \texttt{mesh\_identifier}} Introduced in UFC version 2.0. \begin{code} int mesh_identifier; \end{code} The integer \texttt{mesh\_identifier} can be used during callbacks to the \texttt{evaluate} function of \texttt{ufc::function} to specify a global identifier for the mesh on which the function is being evaluated. This allows \texttt{ufc::function} subclasses to handle evaluation differently on different meshes. If not used, this variable should be set to \texttt{-1}. \section{The class \texttt{ufc::function}} \index{\texttt{ufc::function}} The class \texttt{ufc::function} is an interface for evaluation of general tensor-valued functions on the cells of a mesh. \subsection{The function \texttt{evaluate}} \begin{code} virtual void evaluate(double* values, const double* coordinates, const cell& c) const = 0; \end{code} The only function in this class is \texttt{evaluate}, which evaluates all the value components of the function at a given point in a given cell of the mesh. The output of \texttt{evaluate} should be written to the array \texttt{values}. For a scalar-valued function, a single value should be written to \texttt{values[0]}. For general tensor-valued functions, the values should be written in a flattened row-major ordering of the tensor values. Thus, for a function $f : K \rightarrow \R^{2x2}$ (where $A = f(x)$ is a $2 \times 2$ matrix), the array \texttt{values} should contain the values $A_{11}, A_{12}, A_{21}, A_{22}$ in this order. The input to \texttt{evaluate} are the coordinates of a point in a cell and the UFC view of the cell containing that point. See also the description of \texttt{ufc::finite\_element::evaluate\_dof} below. \section{The class \texttt{ufc::finite\_element}} \index{\texttt{ufc::finite\_element}} The class \texttt{ufc::finite\_element} represents a finite element in the classical Ciarlet sense~\cite{Cia78}, or rather a particular instance of a finite element for a particular choice of nodal basis functions. Thus, a \texttt{ufc::finite\_element} has functions for accessing the shape of the finite element, the dimension of the polynomial function space, the basis functions of the function space (and their derivatives), and the linear functionals defining the degrees of freedom. In addition, a \texttt{ufc::finite\_element} provides functionality for interpolation. \subsection{The function \texttt{signature}} \begin{code} virtual const char* signature() const = 0; \end{code} This function returns a signature string that uniquely identifies the finite element. This can be used to compare whether or not two given \texttt{ufc::fi\-nite\_element} objects are identical. \subsection{The function \texttt{cell\_shape}} \begin{code} virtual shape cell_shape() const = 0; \end{code} This function returns the shape of the cell the finite element is defined on. \subsection{The function \texttt{topological\_dimension}} Introduced in UFC version 2.0. \begin{code} virtual unsigned int topological_dimension() const = 0; \end{code} This function returns the topological dimension of the cell the finite element is defined on. \subsection{The function \texttt{geometric\_dimension}} Introduced in UFC version 2.0. \begin{code} virtual unsigned int geometric_dimension() const = 0; \end{code} This function returns the geometric dimension of the cell the finite element is defined on. \subsection{The function \texttt{space\_dimension}} \begin{code} virtual unsigned int space_dimension() const = 0; \end{code} This function returns the dimension of the local finite element space ($|V_h^K|$), which is equal to the number of basis functions. This should also be equal to the value of \texttt{local\_dimension()} for the corresponding \texttt{ufc::dofmap} (see below). \subsection{The function \texttt{value\_rank}} \begin{code} virtual unsigned int value_rank() const = 0; \end{code} A finite element can have general tensor-valued basis functions. The function \texttt{value\_rank} returns the rank of the value space of the basis functions. For a scalar element, this function should return zero, for vector-valued functions it should return one, for matrix-valued functions it should return two, etc. For mixed elements, this may not always make sense, for example with a tensor-vector-scalar element. Thus the value rank of a mixed element must be 1 if any of the subelements have different value ranks. \subsection{The function \texttt{value\_dimension}} \begin{code} virtual unsigned int value_dimension(unsigned int i) const = 0; \end{code} This function returns the dimension of the value space of the finite element basis functions for the given axis, where the given axis must be a number between zero and the value rank minus one. Note that the total size (number of values) of the value space is obtained as the product of \texttt{value\_dimension(i)} for $0 \le i <$ \texttt{value\_rank()}. For a mixed element with value rank 1 Since the value rank of a mixed element must be 1 if any of the subelements have different value ranks, \texttt{value\_dimension(0)} is then the total value size of all the subelements. \subsection{The function \texttt{evaluate\_basis}} \begin{code} virtual void evaluate_basis(unsigned int i, double* values, const double* coordinates, const cell& c) const = 0; \end{code} This function evaluates basis function \texttt{i} at the given \texttt{coordinates} within the given cell \texttt{c}, and stores the values in the array \texttt{values}. The size of the output array should be equal to size of the value space (see \texttt{value\_dimension} above). The point defined by \texttt{coordinates} should be located inside the cell~\texttt{c}. If the point is located outside the cell, then the result is undefined.~\footnote{In particular, the basis functions generated by FIAT/FFC are undefined along the line $y = 1$ on the UFC reference element since the collapsed cube mapping used by FIAT is singular along that line.} \subsection{The function \texttt{evaluate\_basis\_all}} Introduced in UFC version 1.1. \begin{code} virtual void evaluate_basis_all(double* values, const double* coordinates, const cell& c) const = 0; \end{code} As \texttt{evaluate\_basis}, but evaluates all basis functions at once, which can be implemented much more effectively than multiple calls to \texttt{evaluate\_basis}. The size of the output array should be equal to size of the value space times the number of basis functions. The computed values for a single basis function are placed contiguously in the array. Note that just as for \texttt{evaluate\_basis}, the point defined by \texttt{coordinates} should be located inside the cell~\texttt{c}. The result is otherwise undefined. \subsection{The function \texttt{evaluate\_basis\_derivatives}} \begin{code} virtual void evaluate_basis_derivatives(unsigned int i, unsigned int n, double* values, const double* coordinates, const cell& c) const = 0; \end{code} This function evaluates all order \texttt{n} derivatives of basis function \texttt{i} at the given \texttt{coordinates} within the given \texttt{cell}, and stores the values in the array \texttt{values}. Derivatives may be obtained up to the polynomial degree of the finite element function space with higher degree derivatives evaluating to zero. The number of derivatives is given by $d^n$ where $d$ is the geometric dimension of the cell. For $n = 1$, $d = 3$, the order of the derivatives is naturally $\partial/\partial x$, $\partial/\partial y$, $\partial/\partial z$. For $n = 2$, $d = 3$, the order of the derivatives is $\frac{\partial^2}{\partial x\partial x}, \frac{\partial^2}{\partial x\partial y}, \ldots, \frac{\partial^2}{\partial z\partial z}$. Thus, the derivatives are stored in a flattened row-major ordering based on the derivative spatial dimensions. For tensor-valued basis functions, the ordering of derivatives is row-major based on the value space dimensions followed by the derivative spatial dimensions. Note that just as for \texttt{evaluate\_basis}, the point defined by \texttt{coordinates} should be located inside the cell~\texttt{c}. The result is otherwise undefined. \subsection{The function \texttt{evaluate\_basis\_derivatives\_all}} Introduced in UFC version 1.1. \begin{code} virtual void evaluate_basis_derivatives_all(unsigned int n, double* values, const double* coordinates, const cell& c) const = 0; \end{code} As \texttt{evaluate\_basis\_derivatives}, but evaluated for all basis functions at once, which can be implemented much more effectively than multiple calls to \texttt{evaluate\_basis\_derivatives}. The size of the output array should be equal to the corresponding size defined for \texttt{evaluate\_basis\_derivatives} times the number of basis functions. The computed values for a single basis function are placed contiguously in the array. Note that just as for \texttt{evaluate\_basis}, the point defined by \texttt{coordinates} should be located inside the cell~\texttt{c}. The result is otherwise undefined. \subsection{The function \texttt{evaluate\_dof}} \begin{code} virtual double evaluate_dof(unsigned int i, const function& f, const cell& c) const = 0; \end{code} This function evaluates and returns the value of the degree of freedom \texttt{i} (which is a linear functional) on the given function \texttt{f}. For example, the degrees of freedom for Lagrange finite elements are given by evaluation of \texttt{f} at a set of points. Other examples of degrees of freedom include weighted integrals over facets or normal components on facets. \subsection{The function \texttt{evaluate\_dofs}} Introduced in UFC version 1.1. \begin{code} virtual void evaluate_dofs(double* values, const function& f, const cell& c) const = 0; \end{code} Vectorized version of \texttt{evaluate\_dof} for efficiency, returning the values of all degrees of freedom in the array \texttt{values}. \subsection{The function \texttt{interpolate\_vertex\_values}} \begin{code} virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const cell& c) const = 0; \end{code} This function takes as input the array \texttt{dof\_values} containing the expansion coefficients for some function in the nodal basis and computes the values of that function at the vertices of the given cell, storing those values in the array \texttt{vertex\_values}. If the function is tensor-valued, the values are stored in the array \texttt{vertex\_values} row-major on the list of vertices followed by the row-major ordering of the tensor values as described above. \subsection{The function \texttt{map\_from\_reference\_cell}} Introduced in UFC version 2.0. \begin{code} virtual void map_from_reference_cell(double* x, const double* xhat, const cell& c) = 0; \end{code} This function maps a given coordinate \texttt{xhat} on the reference cell to a coordinate \texttt{x} on a given \texttt{ufc::cell}. \subsection{The function \texttt{map\_to\_reference\_cell}} Introduced in UFC version 2.0. \begin{code} virtual void map_to_reference_cell(double* xhat, const double* x, const cell& c) = 0; \end{code} This function maps a given coordinate \texttt{x} on a given \texttt{ufc::cell} to a coordinate \texttt{xhat} on the reference cell. \subsection{The function \texttt{num\_sub\_elements}} \begin{code} virtual unsigned int num_sub_elements() const = 0; \end{code} This function returns the number of subelements for a nested (mixed) element. For simple elements (non-nested), this function should return one. A nested element is an element that is defined from a set of elements by taking the direct sum (tensor product) of the polynomial spaces of those elements. For example, the basis functions $\psi_1, \psi_2, \ldots, \psi_m$ of a vector-valued Lagrange element may be constructed from a scalar Lagrange element by repeating the basis functions $\phi_1, \phi_2, \ldots, \phi_n$ of the scalar element and padding with zeros: $\psi_1 = (\phi_1, 0), \psi_2 = (\phi_2, 0), \ldots, \psi_n = (\phi_n, 0), \psi_{n+1} = (0, \phi_1), \psi_{n+2} = (0, \phi_2), \ldots$. Finite elements may be nested at arbitrary depth. For example, a mixed Taylor--Hood element may be created by combining a vector-valued quadratic Lagrange finite element with a scalar linear Lagrange finite element, and the vector-valued element may in turn be created by combining a set of scalar quadratic Lagrange elements. \subsection{The function \texttt{create\_sub\_element}} \begin{code} virtual finite_element* create_sub_element(unsigned int i) const = 0; \end{code} This factory function constructs a \texttt{ufc::finite\_element} object for subelement \texttt{i}. The argument \texttt{i} must be an integer between zero and the number of subelements (\texttt{num\_sub\_elements}) minus one. If the element is simple (non-nested), this function returns a zero pointer. The caller is responsible for deleting the returned object. Note that in earlier versions of UFC, this function returned a copy of the element itself in the case of a simple element. To create a copy of the element, use the \texttt{create} function instead. \subsection{The function \texttt{create}} Introduced in UFC version 2.0. \begin{code} virtual finite_element* create() const = 0; \end{code} This factory function creates a new instance of the generated \texttt{ufc::finite\_\-element} subclass. \section{The class \texttt{ufc::dofmap}} \index{\texttt{ufc::dofmap}} This class represents the local-to-global mapping of degrees of freedom (dofs), or rather one particular instance of such a mapping (there are many possible local-to-global mappings) as defined in Equation \eqref{eq:iota_K}. The most central function of this class is \texttt{tabulate\_dofs}, which tabulates the local-to-global mapping from the degree of freedom indices on a local cell to a global vector of degree of freedom indices. \subsection{The function \texttt{signature}} \begin{code} virtual const char* signature() const = 0; \end{code} This function returns a signature string that uniquely identifies the dofmap. This can be used to compare whether or not two given \texttt{ufc::dofmap} objects are identical. (This may be used to optimize the assembly of forms by caching previously computed dofmaps.) \subsection{The function \texttt{needs\_mesh\_entities}} \begin{code} virtual bool needs_mesh_entities(unsigned int d) const = 0; \end{code} This function returns true if the \texttt{ufc::dofmap} requires mesh entities of topological dimension \texttt{d} to be available in \texttt{ufc::cell} arguments. Thus, if this function returns false for a given value of \texttt{d}, then the array \texttt{entity\_indices[d]} of the \texttt{ufc::cell} data structure will not be used during calls to \texttt{ufc::dofmap} functions. In those cases, the array \texttt{entity\_indices[d]} may be set to zero. This may be used to check which entities must be generated to tabulate the local-to-global mapping. For example, linear Lagrange elements will only need to know the vertices of each cell in the mesh, while quadratic Lagrange elements will also need to know the edges of each cell in the mesh. \subsection{The function \texttt{init\_mesh}} \begin{code} virtual bool init_mesh(const mesh& mesh) = 0; \end{code} This function initializes the dofmap for a given mesh. If it returns true, calls to \texttt{init\_cell} and \texttt{init\_cell\_finalize} are required to complete the initialization. The function \texttt{global\_dimension} be may only be called when the initialization is complete. \subsection{The function \texttt{init\_cell}} \begin{code} virtual void init_cell(const mesh& m, const cell& c) = 0; \end{code} For \texttt{ufc::dofmap} objects where \texttt{init\_mesh} returns true, this function must be called for each cell in the mesh to initialize the dofmap. \subsection{The function \texttt{init\_cell\_finalize}} \begin{code} virtual void init_cell_finalize() = 0; \end{code} For \texttt{ufc::dofmap} objects where \texttt{init\_mesh} returns true, this function must be called after \texttt{init\_cell} is called for each cell in the mesh to complete initialization of the dofmap. \subsection{The function \texttt{topological\_dimension}} Introduced in UFC version 1.1. \begin{code} virtual unsigned int topological_dimension() const = 0; \end{code} This function returns the topological dimension of the associated cell shape. \subsection{The function \texttt{geometric\_dimension}} Introduced in UFC version 2.0. \begin{code} virtual unsigned int geometric_dimension() const = 0; \end{code} This function returns the geometric dimension of the associated cell shape. \subsection{The function \texttt{global\_dimension}} \begin{code} virtual unsigned int global_dimension() const = 0; \end{code} This function returns the dimension of the global finite element space on the mesh that the \texttt{ufc::dofmap} has been initialized for. The result of calling this function before the initialization is complete is undefined. \subsection{The function \texttt{local\_dimension}} Changed in version 1.2. \begin{code} virtual unsigned int local_dimension(const cell& c) const = 0; \end{code} This function returns the dimension of the local finite element space on a given cell. \subsection{The function \texttt{max\_local\_dimension}} Introduced in UFC version 1.2. \begin{code} virtual unsigned int max_local_dimension() const = 0; \end{code} This function returns the maximum dimension of the local finite element space on a single cell. \subsection{The function \texttt{num\_facet\_dofs}} \begin{code} virtual unsigned int num_facet_dofs() const = 0; \end{code} This function returns the number of dofs associated with a single facet of a cell, including all dofs associated with mesh entities of lower dimension incident with the facet. For example on a tetrahedron this will include dofs associated with edges and vertices of the triangle face. This is also the number of dofs that should be set if a Dirichlet boundary condition is applied to a single facet. \subsection{The function \texttt{num\_entity\_dofs}} Introduced in UFC version 1.1. \begin{code} virtual unsigned int num_entity_dofs(unsigned int d) const = 0; \end{code} This function returns the number of dofs associated with a single mesh entity of dimension \texttt{d} in a cell, not including dofs associated with incident entities of lower dimension (unlike \texttt{num\_facet\_dofs()}). It is assumed that all cells of the mesh have the same number of degrees of freedom on each mesh entity of the same dimension. \subsection{The function \texttt{tabulate\_dofs}} \begin{code} virtual void tabulate_dofs(unsigned int* dofs, const mesh& m, const cell& c) const = 0; \end{code} This function tabulates the global dof indices corresponding to each dof on the given cell. The size of the output array \texttt{dofs} should be equal to the value returned by \texttt{local\_dimension()}. \subsection{The function \texttt{tabulate\_facet\_dofs}} \begin{code} virtual void tabulate_facet_dofs(unsigned int* dofs, unsigned int facet) const = 0; \end{code} This function tabulates the local dof indices associated with a given local facet, including all dofs associated with mesh entities of lower dimension incident with the facet. The size of the output array \texttt{dofs} should equal the value returned by \texttt{num\_facet\_dofs}. \subsection{The function \texttt{tabulate\_entity\_dofs}} Introduced in UFC version 1.1. \begin{code} virtual void tabulate_entity_dofs(unsigned int* dofs, unsigned int d, unsigned int i) const = 0; \end{code} This function tabulates the local dof indices associated with a given local mesh entity \texttt{i} of dimension \texttt{d}, i.e. mesh entity (d, i), not including dofs associated with incident entities of lower dimension (unlike \texttt{tabulate\_facet\_dofs}). The size of the output array \texttt{dofs} should equal the value returned by the function \texttt{num\_entity\_dofs(d)}. As an example, calling \texttt{tabulate\_entity\_dofs} for a face (d = 2) should yield only the dofs associated with the face that are not associated with vertices and edges. Thus \texttt{tabulate\_entity\_dofs} can be used to build connectivity information. \subsection{The function \texttt{tabulate\_coordinates}} \begin{code} virtual void tabulate_coordinates(double** coordinates, const cell& c) const = 0; \end{code} This function tabulates the coordinates for each dof on the given cell. For Lagrange elements, this function will tabulate a set of points on the given cell such that the dofs of the finite element are given by evaluation at those points. For elements that do not have a direct relationship between coordinates and dofs, an attempt should be made at a sensible implementation of this function. For example, if a dof is defined as the integral over a facet, the midpoint of the facet can be used. If no other choice makes sense, the midpoint of the cell can be used as a last resort. This function must thus be used with care if non-Lagrangian elements are used. The size of the output array \texttt{coordinates} should be equal to the value returned by \texttt{local\_dimension()} and the size of each subarray \texttt{coordi\-nates[0]}, \texttt{coordinates[1]} etc should be equal to the geometric dimension of the mesh, which can be obtained with the function \texttt{dofmap::geometric\_\-dimension()}. \subsection{The function \texttt{num\_sub\_dofmaps}} \begin{code} virtual unsigned int num_sub_dofmaps() const = 0; \end{code} This function returns the number of sub-dofmaps for a nested (mixed) element. For a discussion on the subelement concept, see the documentation of the function \texttt{ufc::finite\_element::num\_sub\_elements}. For simple elements (non-nested), this function should return one. \subsection{The function \texttt{create\_sub\_dofmap}} \begin{code} virtual dofmap* create_sub_dofmap(unsigned int i) const = 0; \end{code} This factory function constructs a \texttt{ufc::dofmap} object for subelement \texttt{i}. The argument \texttt{i} must be a number between zero and the number of sub-dofmaps (\texttt{num\_sub\_dofmaps}) minus one. If the dofmap is simple (non-nested), this function returns a zero pointer. The caller is responsible for deleting the returned object. Note that in earlier versions of UFC, this function returned a copy of the dofmap itself in the case of a simple element. To create a copy of the element, use the \texttt{create} function instead. \subsection{The function \texttt{create}} Introduced in UFC version 2.0. \begin{code} virtual dofmap* create() const = 0; \end{code} This factory function creates a new instance of the generated \texttt{ufc::dofmap} subclass. \section{The integral classes} As described in Section~\ref{sec:assembly}, and in particular Equation \eqref{eq:form_integrals}, the global sparse tensor (the ``stiffness matrix'') representing a given form (differential operator) may be assembled by summing the contributions from the local cells, exterior facets and interior facets of the mesh. These contributions are represented in the UFC interface by the classes \texttt{cell\_integral}, \texttt{exterior\_facet\_integral} and \texttt{interior\_facet\_integral}. Each of these three integral classes has a single function \texttt{tabulate\_tensor} which may be called to compute the corresponding local contribution (cell tensor, exterior facet tensor or interior facet tensor). \section{The class \texttt{ufc::cell\_integral}} \index{\texttt{ufc::cell\_integral}} The class \texttt{ufc::cell\_integral} represents the integral of a form over a local cell in a finite element mesh. It has a single function \texttt{tabulate\_tensor} which may be called to tabulate the values of the cell tensor for a given cell. \subsection{The function \texttt{tabulate\_tensor}} \index{\texttt{tabulate\_tensor}} \begin{code} virtual void tabulate_tensor(double* A, const double * const * w, const cell& c) const = 0; \end{code} This function tabulates the values of the cell tensor for a form into the given array \texttt{A}. The size of this array should be equal to the product of the local space dimensions for the set of finite element function spaces corresponding to the arguments of the form. For example, when computing the matrix for a bilinear form defined on piecewise linear scalar elements on triangles, the space dimension of the local finite element is three and so the size of the array \texttt{A} should be $3 \times 3 = 9$. The array \texttt{w} should contain the expansion coefficients for all \emph{coefficients} of the form in the finite element nodal basis for each corresponding function space. Thus, the size of the array \texttt{w} should be equal to the number of coefficients~$n$, and the size of each each array \texttt{w[0]}, \texttt{w[1]} etc should be equal to the space dimension of the corresponding local finite element space. \subsection{The function \texttt{tabulate\_tensor} (quadrature version)} \index{\texttt{tabulate\_tensor} (quadrature version)} Introduced in UFC version version 2.0 \begin{code} virtual void tabulate_tensor(double* A, const double * const * w, const cell& c, unsigned int num_quadrature_points, const double * const * quadrature_points, const double* quadrature_weights) const = 0; \end{code} This function is identical to \texttt{tabulate\_tensor} described above but computes the integral over the cell using the given set of quadrature points and weights. Note that the quadrature points should be specified on the reference cell. By a careful choice of quadrature points, this function can be used to integrate over subsets of cells. \section{The class \texttt{ufc::exterior\_facet\_integral}} \index{\texttt{ufc::exterior\_facet\_integral}} The class \texttt{ufc::exterior\_facet\_integral} represents the integral of a form over a local exterior facet (boundary facet) in a finite element mesh. It has a single function \texttt{tabulate\_tensor} which may be called to tabulate the values of the exterior facet tensor for a given facet. \subsection{The function \texttt{tabulate\_tensor}} \index{\texttt{tabulate\_tensor}} \begin{code} virtual void tabulate_tensor(double* A, const double * const * w, const cell& c, unsigned int facet) const = 0; \end{code} The arrays \texttt{A} and \texttt{w} have the same function and should have the same sizes as described in the documentation for \texttt{cell\_integral::tabulate\_tensor}. Thus, the values of the exterior facet integral will be tabulated into the array \texttt{A} and the nodal basis expansions of all coefficients should be provided in the array \texttt{w}. The additional argument \texttt{facet} should specify the local number of the facet with respect to its (single) incident cell. Thus, when the facet is an edge of a triangle, the argument \texttt{facet} should be an integer between zero and two (0, 1, 2) and when the facet is a facet of a tetrahedron, the argument \texttt{facet} should be an integer between zero and three (0, 1, 2, 3). \subsection{The function \texttt{tabulate\_tensor} (quadrature version)} \index{\texttt{tabulate\_tensor} (quadrature version)} Introduced in version version 2.0 \begin{code} virtual void tabulate_tensor(double* A, const double * const * w, const cell& c, unsigned int num_quadrature_points, const double * const * quadrature_points, const double* quadrature_weights) const = 0; \end{code} This function is identical to \texttt{tabulate\_tensor} described above but computes the integral over the cell using the given set of quadrature points and weights. Note that the quadrature points should be specified on the reference cell. By a careful choice of quadrature points, this function can be used to integrate over subsets of facets. \section{The class \texttt{ufc::interior\_facet\_integral}} \index{\texttt{ufc::interior\_facet\_integral}} The class \texttt{ufc::interior\_facet\_integral} represents the integral of a form over a local interior facet in a finite element mesh. It has a single function \texttt{tabulate\_tensor} which may be called to tabulate the values of the interior facet tensor for a given facet. \subsection{The function \texttt{tabulate\_tensor}} \begin{code} virtual void tabulate_tensor(double* A, const double * const * w, const cell& c0, const cell& c1, unsigned int facet0, unsigned int facet1) const = 0; \end{code} Just as for the \texttt{cell\_integral} and \texttt{exterior\_facet\_integral} classes, the \texttt{tabulate\_tensor} function for the class \texttt{interior\_facet\_integral} tabulates the values of the local (interior facet) tensor into the array \texttt{A}, given the nodal basis expansions of the form coefficients in the array \texttt{w}. However, the interior facet tensor contains contributions from the two incident cells of an interior facet and thus the dimensions of these arrays are different. On each interior facet, the two incident (neighboring) cells form a ``macro cell'' consisting of the total set of local basis functions on the two cells. The set of basis functions on the macro element is obtained by extending the basis functions on each of the two cells by zero to the macro cell. Thus, the space dimension of the finite element function space on the macro element is twice the size of the finite element function space on a single cell. The ordering of basis functions and degrees of freedom on the macro cell is obtained by first enumerating the basis functions and degrees of freedom on one of the two cells and then the basis functions and degrees of freedom on the second cell. Thus the size of the array \texttt{A} should be equal to the product of twice the local space dimensions for the set of finite element function spaces corresponding to the arguments of the form. For example, when computing the matrix for a bilinear form defined on piecewise linear elements on triangles, the space dimension of the local finite element is three and so the size of the array \texttt{A} should be $6 \times 6 = 36$. Similarly, the array \texttt{w} should contain the expansion coefficients for all \emph{coefficients} of the form in the finite element nodal basis for each corresponding function space on the macro cell. Thus, the size of the array \texttt{w} should be equal to the number of coefficients~$n$ and the size of each each array \texttt{w[0]}, \texttt{w[1]} etc should be equal to twice the space dimension of the corresponding local finite element space. The additional arguments \texttt{facet0} and \texttt{facet1} should specify the local number of the facet with respect to its two incident cells. Thus, when the facet is an edge of a triangle, each of these arguments may be an integer between zero and two (0, 1, 2) and when the facet is a face of a tetrahedron, each of these arguments may be an integer between zero and three (0, 1, 2, 3). \subsection{The function \texttt{tabulate\_tensor} (quadrature version)} \index{\texttt{tabulate\_tensor} (quadrature version)} Introduced in version version 2.0 \begin{code} virtual void tabulate_tensor(double* A, const double * const * w, const cell& c, unsigned int num_quadrature_points, const double * const * quadrature_points, const double* quadrature_weights) const = 0; \end{code} This function is identical to \texttt{tabulate\_tensor} described above but computes the integral over the cell using the given set of quadrature points and weights. Note that the quadrature points should be specified on the reference cell. By a careful choice of quadrature points, this function can be used to integrate over subsets of facets. \section{The class \texttt{ufc::form}} \index{\texttt{ufc::form}} The \texttt{ufc::form} class is the central part of the UFC interface and it represents a form \begin{equation} a = a(v_1, \ldots, v_r; w_1, \ldots, w_n), \end{equation} defined on the product space $V_h^1 \times V_h^2 \times \cdots \times V_h^r \times W_h^1 \times W_h^2 \times \cdots \times W_h^n$ of two sets $\{V_h^j\}_{j=1}^r, \{W_h^j\}_{j=1}^n$ of finite element function spaces on a triangulation $\mathcal{T}$ of a domain $\Omega \subset \R^d$. A \texttt{ufc::form} provides functions for accessing the rank~$r$ and number of coefficients~$n$ for a form, and factory functions for creating UFC objects for the corresponding cell integrals, exterior facet integrals, interior facet integrals, and all associated finite elements and dofmaps (local-to-global mappings). \subsection{The function \texttt{signature}} \begin{code} virtual const char* signature() const = 0; \end{code} This function returns a signature string that uniquely identifies the form. This can be used to compare whether or not two given \texttt{ufc::form} objects are identical. \subsection{The function \texttt{rank}} \begin{code} virtual unsigned int rank() const = 0; \end{code} This function returns the rank~$r$ of the global tensor generated by the form (the arity of the form). \subsection{The function \texttt{num\_coefficients}} \begin{code} virtual unsigned int num_coefficients() const = 0; \end{code} This function returns the number of coefficients~$n$ for the form. Note that all integral terms of a form must have the same coefficients, even if not all coefficients are present in each term of the form. \subsection{The function \texttt{num\_cell\_domains}} \begin{code} virtual unsigned int num_cell_domains() const = 0; \end{code} This function returns the number of different cell domains for the form. A form may have an arbitrary number of integrals over disjoint subdomains of the mesh. \subsection{The function \texttt{num\_exterior\_facet\_domains}} \begin{code} virtual unsigned int num_exterior_facet_domains() const = 0; \end{code} This function returns the number of different exterior facet domains for the form. A form may have an arbitrary number of integrals over disjoint subdomains of the mesh boundary. \subsection{The function \texttt{num\_interior\_facet\_domains}} \begin{code} virtual unsigned int num_interior_facet_domains() const = 0; \end{code} This function returns the number of different interior facet domains for the form. A form may have an arbitrary number of integrals over disjoint subsets of the interior facets of the mesh. \subsection{The function \texttt{create\_finite\_element}} \begin{code} virtual finite_element* create_finite_element(unsigned int i) const = 0; \end{code} This factory function constructs a \texttt{ufc::finite\_element} object for form argument \texttt{i}. A form with rank~$r$ and number of coefficients~$n$ has $r + n$ arguments, so this function returns the finite element object for tensor axis $i$ if $i < r$, or the finite element for coefficient $i - r$ if $i \geq r$. The caller is responsible for deleting the returned object. \subsection{The function \texttt{create\_dofmap}} \begin{code} virtual dofmap* create_dofmap(unsigned int i) const = 0; \end{code} This factory function constructs a \texttt{ufc::dofmap} object for form argument \texttt{i}. A form with rank~$r$ and number of coefficients~$n$ has $r + n$ arguments, so this function returns the dofmap object for tensor axis $i$ if $i < r$, or the dofmap for coefficient $i - r$ if $i \geq r$. The caller is responsible for deleting the returned object. \subsection{The function \texttt{create\_cell\_integral}} \begin{code} virtual cell_integral* create_cell_integral(unsigned int i) const = 0; \end{code} This factory function constructs a \texttt{cell\_integral} object for cell domain \texttt{i}. The caller is responsible for deleting the returned object. If the integral evaluates to zero, this function may return a null pointer. \subsection{The function \texttt{create\_exterior\_facet\_integral}} \begin{code} virtual exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const = 0; \end{code} This factory function constructs an \texttt{exterior\_facet\_integral} object for exterior facet domain \texttt{i}. The caller is responsible for deleting the returned object. If the integral evaluates to zero, this function may return a null pointer. \subsection{The function \texttt{create\_interior\_facet\_integral}} \begin{code} virtual interior_facet_integral* create_interior_facet_integral(unsigned int i) const = 0; \end{code} This factory function constructs an \texttt{interior\_facet\_integral} object for interior facet domain \texttt{i}. The caller is responsible for deleting the returned object. If the integral evaluates to zero, this function may return a null pointer. ufc-2.3.0/doc/manual/chapters/interface_cpp.tex000066400000000000000000000003551226277264200214650ustar00rootroot00000000000000\chapter{C++ Interface} Below follows a verbatim copy of the complete UFC interface which is specified in the header file~\texttt{ufc.h}. \scriptsize \VerbatimInput[frame=single,rulecolor=\color{blue}]{../../src/ufc/ufc.h} \normalsize ufc-2.3.0/doc/manual/chapters/introduction.tex000066400000000000000000000101311226277264200213750ustar00rootroot00000000000000\chapter{Introduction} \label{sec:introduction} Large parts of a finite element program are similar from problem to problem and can therefore be coded as a general, reusable library. Mesh data structures, linear algebra and finite element assembly are examples of operations that are naturally coded in a problem-independent way and made available in reusable libraries~\cite{www:fenics,www:petsc,www:sundance,www:deal.II,www:trilinos,www:diffpack}. However, some parts of a finite element program are difficult to code in a problem-independent way. In particular, this includes the evaluation of the \emph{element tensor} (the `element stiffness matrix'), that is, the evaluation of the local contribution from a finite element to a global sparse tensor (the ``stiffness matrix'') representing a discretized differential operator. These parts must thus be implemented by the application programmer for each specific combination of differential equation and discretization (finite element spaces). \index{form compilers} \index{FFC} \index{SyFi} However, domain-specific compilers such as FFC~\cite{www:ffc,logg:article:07,logg:article:09,logg:article:10,logg:article:11} and SyFi~\cite{www:syfi} make it possible to automatically generate the code for the evaluation of the element tensor. These \emph{form compilers} accept as input a high-level description of a finite element variational form and generate low-level code code for efficient evaluation of the element tensor and associated quantities. It thus becomes important to specify the \emph{interface} between form compilers and finite element assemblers such that the code generated by FFC, SyFi and other form compilers can be used to assemble finite element matrices and vectors (and in general tensors). \section{Unified Form-assembly Code} UFC (Unified Form-assembly Code) is a unified framework for finite element assembly. More precisely, it defines a fixed interface for communicating low level routines (functions) for evaluating and assembling finite element variational forms. The UFC interface consists of a single header file \texttt{ufc.h} that specifies a C++ interface that must be implemented by code that complies with the UFC specification. Both FFC (since version 0.4.0) and SyFi (since version 0.3.4) generate code that complies with the UFC specification. Thus, code generated by FFC and SyFi may be used interchangeably by any UFC-based finite element assembler, such as DOLFIN~\cite{www:dolfin}. \section{Aim and scope} The UFC interface has been designed to make a minimal amount of assumptions on the form compilers generating the UFC code and the assemblers built on top of the UFC specification. Thus, the UFC specification provides a minimal amount of abstractions and data structures. Programmers wishing to implement the UFC specification will typically want to create system-specific (but simple) wrappers for the generated code. Few assumptions have also been made on the underlying finite element methodology. The current specification is limited to affinely mapped cells, but does not restrict the mapping of finite element function spaces. Thus, UFC code may be generated for elements where basis functions are transformed from the reference cell by the affine mapping, as well as for elements where the basis functions must be transformed by the Piola mapping. UFC code has been successfully generated and used in finite element codes for standard continuous Galerkin methods (Lagrange finite elements of arbitrary order), discontinuous Galerkin methods (including integrals of jumps and averages over interior facets) and mixed methods (including Brezzi--Douglas--Marini and Raviart--Thomas elements). \section{Outline} In the next section, we give an overview of finite element assembly and explain how the code generated by form compilers may be used as the basic building blocks in the assembly algorithm. We then present the UFC interface in detail in Section~\ref{sec:interface}. In Section~\ref{sec:referencecells} and Section~\ref{sec:numbering}, we define the reference cells and numbering conventions that must be followed by UFC-based form compilers and assemblers. ufc-2.3.0/doc/manual/chapters/license.tex000066400000000000000000000002201226277264200202740ustar00rootroot00000000000000\chapter{License} \index{license} The UFC specification, and in particular the header file \texttt{ufc.h}, is released into the public domain. ufc-2.3.0/doc/manual/chapters/numbering.tex000066400000000000000000000001361226277264200206460ustar00rootroot00000000000000\chapter{Numbering of mesh entities} \label{sec:numbering} \input{chapters/numbering_common} ufc-2.3.0/doc/manual/chapters/numbering_common.tex000066400000000000000000000337701226277264200222300ustar00rootroot00000000000000\index{numbering} The UFC specification dictates a certain numbering of the vertices, edges etc. of the cells of a finite element mesh. First, an \emph{ad hoc} numbering is picked for the vertices of each cell. Then, the remaining entities are ordered based on a simple rule, as described in detail below. \section{Basic concepts} \index{mesh entity} \index{topological dimension} The topological entities of a cell (or mesh) are referred to as \emph{mesh entities}. A mesh entity can be identified by a pair $(d, i)$, where $d$ is the topological dimension of the mesh entity and $i$ is a unique index of the mesh entity. Mesh entities are numbered within each topological dimension from $0$ to $n_d-1$, where $n_d$ is the number of mesh entities of topological dimension $d$. For convenience, mesh entities of topological dimension $0$ are referred to as \emph{vertices}, entities of dimension $1$ as \emph{edges}, entities of dimension $2$ as \emph{faces}, entities of \emph{codimension} $1$ as \emph{facets} and entities of codimension $0$ as \emph{cells}. These concepts are summarized in Table~\ref{tab:entities}. Thus, the vertices of a tetrahedron are identified as $v_0 = (0, 0)$, $v_1 = (0, 1)$ and $v_2 = (0, 2)$, the edges are $e_0 = (1, 0)$, $e_1 = (1, 1)$, $e_2 = (1, 2)$, $e_3 = (1, 3)$, $e_4 = (1, 4)$ and $e_5 = (1, 5)$, the faces (facets) are $f_0 = (2, 0)$, $f_1 = (2, 1)$, $f_2 = (2, 2)$ and $f_3 = (2, 3)$, and the cell itself is $c_0 = (3, 0)$. \begin{table} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|l|c|c|} \hline Entity & Dimension & Codimension \\ \hline Vertex & $0$ & -- \\ Edge & $1$ & -- \\ Face & $2$ & -- \\ & & \\ Facet & -- & $1$ \\ Cell & -- & $0$ \\ \hline \end{tabular} \caption{Named mesh entities.} \label{tab:entities} \end{center} \end{table} \section{Numbering of vertices} \index{vertex numbering} For simplicial cells (intervals, triangles and tetrahedra) of a finite element mesh, the vertices are numbered locally based on the corresponding global vertex numbers. In particular, a tuple of increasing local vertex numbers corresponds to a tuple of increasing global vertex numbers. This is illustrated in Figure~\ref{fig:numbering_example_triangles} for a mesh consisting of two triangles. \begin{figure}[htbp] \begin{center} \psfrag{v0}{$v_0$} \psfrag{v1}{$v_1$} \psfrag{v2}{$v_2$} \psfrag{0}{$0$} \psfrag{1}{$1$} \psfrag{2}{$2$} \psfrag{3}{$3$} \includegraphics[width=8cm]{eps/numbering_example_triangles.eps} \caption{The vertices of a simplicial mesh are numbered locally based on the corresponding global vertex numbers.} \label{fig:numbering_example_triangles} \end{center} \end{figure} For non-simplicial cells (quadrilaterals and hexahedra), the numbering is arbitrary, as long as each cell is isomorphic to the corresponding reference cell by matching each vertex with the corresponding vertex in the reference cell. This is illustrated in Figure~\ref{fig:numbering_example_quadrilaterals} for a mesh consisting of two quadrilaterals. \begin{figure}[htbp] \begin{center} \psfrag{v0}{$v_0$} \psfrag{v1}{$v_1$} \psfrag{v2}{$v_2$} \psfrag{v3}{$v_3$} \psfrag{0}{$0$} \psfrag{1}{$1$} \psfrag{2}{$2$} \psfrag{3}{$3$} \psfrag{4}{$4$} \psfrag{5}{$5$} \includegraphics[width=8cm]{eps/numbering_example_quadrilaterals.eps} \caption{The local numbering of vertices of a non-simplicial mesh is arbitrary, as long as each cell is isomorphic to the reference cell by matching each vertex to the corresponding vertex of the reference cell.} \label{fig:numbering_example_quadrilaterals} \end{center} \end{figure} \section{Numbering of other mesh entities} When the vertices have been numbered, the remaining mesh entities are numbered within each topological dimension based on a \emph{lexicographical ordering} of the corresponding ordered tuples of \emph{non-incident vertices}. As an illustration, consider the numbering of edges (the mesh entities of topological dimension one) on the reference triangle in Figure~\ref{fig:orderingexample,triangle}. To number the edges of the reference triangle, we identify for each edge the corresponding non-incident vertices. For each edge, there is only one such vertex (the vertex opposite to the edge). We thus identify the three edges in the reference triangle with the tuples $(v_0)$, $(v_1)$ and $(v_2)$. The first of these is edge $e_0$ between vertices $v_1$ and $v_2$ opposite to vertex $v_0$, the second is edge $e_1$ between vertices $v_0$ and $v_2$ opposite to vertex $v_1$, and the third is edge $e_2$ between vertices $v_0$ and $v_1$ opposite to vertex $v_2$. Similarly, we identify the six edges of the reference tetrahedron with the corresponding non-incident tuples $(v_0, v_1)$, $(v_0, v_2)$, $(v_0, v_3)$, $(v_1, v_2)$, $(v_1, v_3)$ and $(v_2, v_3)$. The first of these is edge $e_0$ between vertices $v_2$ and $v_3$ opposite to vertices $v_0$ and $v_1$ as shown in Figure~\ref{fig:orderingexample,tetrahedron}. \begin{figure}[htbp] \begin{center} \psfrag{v0}{$v_0$} \psfrag{v1}{$v_1$} \psfrag{v2}{$v_2$} \psfrag{e0}{$e_0$} \includegraphics[width=5cm]{eps/ordering_example_triangle.eps} \caption{Mesh entities are ordered based on a lexicographical ordering of the corresponding ordered tuples of non-incident vertices. The first edge $e_0$ is non-incident to vertex $v_0$.} \label{fig:orderingexample,triangle} \end{center} \end{figure} \begin{figure}[htbp] \begin{center} \psfrag{v0}{$v_0$} \psfrag{v1}{$v_1$} \psfrag{v2}{$v_2$} \psfrag{v3}{$v_3$} \psfrag{e0}{$e_0$} \includegraphics[width=5cm]{eps/ordering_example_tetrahedron.eps} \caption{Mesh entities are ordered based on a lexicographical ordering of the corresponding ordered tuples of non-incident vertices. The first edge $e_0$ is non-incident to vertices $v_0$ and $v_1$.} \label{fig:orderingexample,tetrahedron} \end{center} \end{figure} \subsection{Relative ordering} The relative ordering of mesh entities with respect to other incident mesh entities follows by sorting the entities by their (global) indices. Thus, the pair of vertices incident to the first edge $e_0$ of a triangular cell is $(v_1, v_2)$, not $(v_2, v_1)$. Similarly, the first face $f_0$ of a tetrahedral cell is incident to vertices $(v_1, v_2, v_3)$. For simplicial cells, the relative ordering in combination with the convention of numbering the vertices locally based on global vertex indices means that two incident cells will always agree on the orientation of incident subsimplices. Thus, two incident triangles will agree on the orientation of the common edge and two incident tetrahedra will agree on the orientation of the common edge(s) and the orientation of the common face (if any). This is illustrated in Figure~\ref{fig:orientation_example_triangles} for two incident triangles sharing a common edge. \begin{figure}[htbp] \begin{center} \psfrag{v0}{$v_0$} \psfrag{v1}{$v_1$} \psfrag{v2}{$v_2$} \psfrag{v3}{$v_3$} \includegraphics[width=9cm]{eps/orientation_example_triangles.eps} \caption{Two incident triangles will always agree on the orientation of the common edge.} \label{fig:orientation_example_triangles} \end{center} \end{figure} \subsection{Limitations} The UFC specification is only concerned with the ordering of mesh entities with respect to entities of larger topological dimension. In other words, the UFC specification is only concerned with the ordering of incidence relations of the class $d - d'$ where $d > d'$. For example, the UFC specification is not concerned with the ordering of incidence relations of the class $0 - 1$, that is, the ordering of edges incident to vertices. \newpage \section{Numbering schemes for reference cells} The numbering scheme is demonstrated below for cells isomorphic to each of the five reference cells. \subsection{Numbering of mesh entities on intervals} \begin{minipage}{\textwidth} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|c|c|c|} \hline Entity & Incident vertices & Non-incident vertices \\ \hline \hline $v_0 = (0, 0)$ & $(v_0)$ & $(v_1)$ \\ \hline $v_1 = (0, 1)$ & $(v_1)$ & $(v_0)$ \\ \hline $c_0 = (1, 0)$ & $(v_0, v_1)$ & $\emptyset$ \\ \hline \end{tabular} \end{center} \end{minipage} \subsection{Numbering of mesh entities on triangular cells} % \begin{minipage}{\textwidth} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|c|c|c|} \hline Entity & Incident vertices & Non-incident vertices \\ \hline \hline $v_0 = (0, 0)$ & $(v_0)$ & $(v_1, v_2)$ \\ \hline $v_1 = (0, 1)$ & $(v_1)$ & $(v_0, v_2)$ \\ \hline $v_2 = (0, 2)$ & $(v_2)$ & $(v_0, v_1)$ \\ \hline $e_0 = (1, 0)$ & $(v_1, v_2)$ & $(v_0)$ \\ \hline $e_1 = (1, 1)$ & $(v_0, v_2)$ & $(v_1)$ \\ \hline $e_2 = (1, 2)$ & $(v_0, v_1)$ & $(v_2)$ \\ \hline $c_0 = (2, 0)$ & $(v_0, v_1, v_2)$ & $\emptyset$ \\ \hline \end{tabular} \end{center} \end{minipage} \subsection{Numbering of mesh entities on quadrilateral cells} % \begin{minipage}{\textwidth} \linespread{1.1}\selectfont \begin{center} \begin{tabular}{|c|c|c|} \hline Entity & Incident vertices & Non-incident vertices \\ \hline \hline $v_0 = (0, 0)$ & $(v_0)$ & $(v_1, v_2, v_3)$ \\ \hline $v_1 = (0, 1)$ & $(v_1)$ & $(v_0, v_2, v_3)$ \\ \hline $v_2 = (0, 2)$ & $(v_2)$ & $(v_0, v_1, v_3)$ \\ \hline $v_3 = (0, 3)$ & $(v_3)$ & $(v_0, v_1, v_2)$ \\ \hline $e_0 = (1, 0)$ & $(v_2, v_3)$ & $(v_0, v_1)$ \\ \hline $e_1 = (1, 1)$ & $(v_1, v_2)$ & $(v_0, v_3)$ \\ \hline $e_2 = (1, 2)$ & $(v_0, v_3)$ & $(v_1, v_2)$ \\ \hline $e_3 = (1, 3)$ & $(v_0, v_1)$ & $(v_2, v_3)$ \\ \hline $c_0 = (2, 0)$ & $(v_0, v_1, v_2, v_3)$ & $\emptyset$ \\ \hline \end{tabular} \end{center} \end{minipage} \subsection{Numbering of mesh entities on tetrahedral cells} % \begin{minipage}{\textwidth} \linespread{1.1}\selectfont \begin{center} \begin{tabular}{|c|c|c|} \hline Entity & Incident vertices & Non-incident vertices \\ \hline \hline $v_0 = (0, 0)$ & $(v_0)$ & $(v_1, v_2, v_3)$ \\ \hline $v_1 = (0, 1)$ & $(v_1)$ & $(v_0, v_2, v_3)$ \\ \hline $v_2 = (0, 2)$ & $(v_2)$ & $(v_0, v_1, v_3)$ \\ \hline $v_3 = (0, 3)$ & $(v_3)$ & $(v_0, v_1, v_2)$ \\ \hline $e_0 = (1, 0)$ & $(v_2, v_3)$ & $(v_0, v_1)$ \\ \hline $e_1 = (1, 1)$ & $(v_1, v_3)$ & $(v_0, v_2)$ \\ \hline $e_2 = (1, 2)$ & $(v_1, v_2)$ & $(v_0, v_3)$ \\ \hline $e_3 = (1, 3)$ & $(v_0, v_3)$ & $(v_1, v_2)$ \\ \hline $e_4 = (1, 4)$ & $(v_0, v_2)$ & $(v_1, v_3)$ \\ \hline $e_5 = (1, 5)$ & $(v_0, v_1)$ & $(v_2, v_3)$ \\ \hline $f_0 = (2, 0)$ & $(v_1, v_2, v_3)$ & $(v_0)$ \\ \hline $f_1 = (2, 1)$ & $(v_0, v_2, v_3)$ & $(v_1)$ \\ \hline $f_2 = (2, 2)$ & $(v_0, v_1, v_3)$ & $(v_2)$ \\ \hline $f_3 = (2, 3)$ & $(v_0, v_1, v_2)$ & $(v_3)$ \\ \hline $c_0 = (3, 0)$ & $(v_0, v_1, v_2, v_3)$ & $\emptyset$ \\ \hline \end{tabular} \end{center} \end{minipage} \vfill \newpage \subsection{Numbering of mesh entities on hexahedral cells} \begin{minipage}{\textwidth} \small \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|c|c|c|} \hline Entity & Incident vertices & Non-incident vertices \\ \hline \hline $v_0 = (0, 0)$ & $(v_0)$ & $(v_1, v_2, v_3, v_4, v_5, v_6, v_7)$ \\ \hline $v_1 = (0, 1)$ & $(v_1)$ & $(v_0, v_2, v_3, v_4, v_5, v_6, v_7)$ \\ \hline $v_2 = (0, 2)$ & $(v_2)$ & $(v_0, v_1, v_3, v_4, v_5, v_6, v_7)$ \\ \hline $v_3 = (0, 3)$ & $(v_3)$ & $(v_0, v_1, v_2, v_4, v_5, v_6, v_7)$ \\ \hline $v_4 = (0, 4)$ & $(v_4)$ & $(v_0, v_1, v_2, v_3, v_5, v_6, v_7)$ \\ \hline $v_5 = (0, 5)$ & $(v_5)$ & $(v_0, v_1, v_2, v_3, v_4, v_6, v_7)$ \\ \hline $v_6 = (0, 6)$ & $(v_6)$ & $(v_0, v_1, v_2, v_3, v_4, v_5, v_7)$ \\ \hline $v_7 = (0, 7)$ & $(v_7)$ & $(v_0, v_1, v_2, v_3, v_4, v_5, v_6)$ \\ \hline $e_0 = (1, 0)$ & $(v_6, v_7)$ & $(v_0, v_1, v_2, v_3, v_4, v_5)$ \\ \hline $e_1 = (1, 1)$ & $(v_5, v_6)$ & $(v_0, v_1, v_2, v_3, v_4, v_7)$ \\ \hline $e_2 = (1, 2)$ & $(v_4, v_7)$ & $(v_0, v_1, v_2, v_3, v_5, v_6)$ \\ \hline $e_3 = (1, 3)$ & $(v_4, v_5)$ & $(v_0, v_1, v_2, v_3, v_6, v_7)$ \\ \hline $e_4 = (1, 4)$ & $(v_3, v_7)$ & $(v_0, v_1, v_2, v_4, v_5, v_6)$ \\ \hline $e_5 = (1, 5)$ & $(v_2, v_6)$ & $(v_0, v_1, v_3, v_4, v_5, v_7)$ \\ \hline $e_6 = (1, 6)$ & $(v_2, v_3)$ & $(v_0, v_1, v_4, v_5, v_6, v_7)$ \\ \hline $e_7 = (1, 7)$ & $(v_1, v_5)$ & $(v_0, v_2, v_3, v_4, v_6, v_7)$ \\ \hline $e_8 = (1, 8)$ & $(v_1, v_2)$ & $(v_0, v_3, v_4, v_5, v_6, v_7)$ \\ \hline $e_9 = (1, 9)$ & $(v_0, v_4)$ & $(v_1, v_2, v_3, v_5, v_6, v_7)$ \\ \hline $e_{10} = (1, 10)$ & $(v_0, v_3)$ & $(v_1, v_2, v_4, v_5, v_6, v_7)$ \\ \hline $e_{11} = (1, 11)$ & $(v_0, v_1)$ & $(v_2, v_3, v_4, v_5, v_6, v_7)$ \\ \hline $f_0 = (2, 0)$ & $(v_4, v_5, v_6, v_7)$ & $(v_0, v_1, v_2, v_3)$ \\ \hline $f_1 = (2, 1)$ & $(v_2, v_3, v_6, v_7)$ & $(v_0, v_1, v_4, v_5)$ \\ \hline $f_2 = (2, 2)$ & $(v_1, v_2, v_5, v_6)$ & $(v_0, v_3, v_4, v_7)$ \\ \hline $f_3 = (2, 3)$ & $(v_0, v_3, v_4, v_7)$ & $(v_1, v_2, v_5, v_6)$ \\ \hline $f_4 = (2, 4)$ & $(v_0, v_1, v_4, v_5)$ & $(v_2, v_3, v_6, v_7)$ \\ \hline $f_5 = (2, 5)$ & $(v_0, v_1, v_2, v_3)$ & $(v_4, v_5, v_6, v_7)$ \\ \hline $c_0 = (3, 0)$ & $(v_0, v_1, v_2, v_3, v_4, v_5, v_6, v_7)$ & $\emptyset$ \\ \hline \end{tabular} \end{center} \end{minipage} ufc-2.3.0/doc/manual/chapters/pythonutils.tex000066400000000000000000000027271226277264200212720ustar00rootroot00000000000000\chapter{Python utilities} \index{Python utilities} \index{code generation} The UFC distribution includes a set of Python utilities for generating code that conforms to the UFC specification. These utilities consist of format string templates for C++ header files (\texttt{.h} files), implementation files (\texttt{.cpp}) and combined header and implementation files (\texttt{.h} files containing both the declaration and definition of the UFC functions). The following format strings are provided: \begin{code} function_combined_{header, implementation, combined} finite_element_{header, implementation, combined} dofmap_{header, implementation, combined} cell_integral_{header, implementation, combined} exterior_facet_integral_{header, implementation, combined} interior_facet_integral_{header, implementation, combined} form_{header, implementation, combined} \end{code} We demonstrate below how to use the format string \texttt{form\_combined} together with a dictionary that specifies the code to be inserted into the format string. Typically, a form compiler will first generate the code to be inserted into the dictionary and then in a later stage write the generated code to file in UFC format using the provided format strings. \begin{code} from ufc import form_combined code = {} code["classname"] = "Poisson", ... code["rank"] = " return 2;", code["num_coefficients"] = " return 0;", code["num_cell_domains"] = " return 1;", ... print form_combined % code \end{code} ufc-2.3.0/doc/manual/chapters/referencecells.tex000066400000000000000000000001351226277264200216400ustar00rootroot00000000000000\chapter{Reference cells} \label{sec:referencecells} \input{chapters/referencecells_common} ufc-2.3.0/doc/manual/chapters/referencecells_common.tex000066400000000000000000000141431226277264200232140ustar00rootroot00000000000000\index{reference cells} The following five reference cells are covered by the UFC specification: the reference \emph{interval}, the reference \emph{triangle}, the reference \emph{quadrilateral}, the reference \emph{tetrahedron} and the reference \emph{hexahedron} (see Table~\ref{tab:ufc_reference_cells}). \begin{table} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|l|c|c|c|} \hline Reference cell & Dimension & \#Vertices & \#Facets \\ \hline \hline The reference interval & 1 & 2 & 2 \\ \hline The reference triangle & 2 & 3 & 3 \\ \hline The reference quadrilateral & 2 & 4 & 4 \\ \hline The reference tetrahedron & 3 & 4 & 4 \\ \hline The reference hexahedron & 3 & 8 & 6 \\ \hline \end{tabular} \caption{Reference cells covered by the UFC specification.} \label{tab:ufc_reference_cells} \end{center} \end{table} The UFC specification assumes that each cell in a finite element mesh is always isomorphic to one of the reference cells. \section{The reference interval} \index{interval} The reference interval is shown in Figure~\ref{fig:interval} and is defined by its two vertices with coordinates as specified in Table~\ref{tab:interval,vertices}. \begin{figure} \begin{center} \psfrag{0}{$0$} \psfrag{1}{$1$} \includegraphics[width=10cm]{eps/interval.eps} \caption{The reference interval.} \label{fig:interval} \end{center} \end{figure} \begin{table} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|c|c|} \hline Vertex & Coordinate \\ \hline \hline $v_0$ & $x = 0$ \\ \hline $v_1$ & $x = 1$ \\ \hline \end{tabular} \caption{Vertex coordinates of the reference interval.} \label{tab:interval,vertices} \end{center} \end{table} \section{The reference triangle} \index{triangle} The reference triangle is shown in Figure~\ref{fig:triangle} and is defined by its three vertices with coordinates as specified in Table~\ref{tab:triangle,vertices}. \begin{figure} \begin{center} \psfrag{v0}{$(0, 0)$} \psfrag{v1}{$(1, 0)$} \psfrag{v2}{$(0, 1)$} \includegraphics[width=8cm]{eps/triangle.eps} \caption{The reference triangle.} \label{fig:triangle} \end{center} \end{figure} \begin{table} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|c|c|} \hline Vertex & Coordinate \\ \hline \hline $v_0$ & $x = (0, 0)$ \\ \hline $v_1$ & $x = (1, 0)$ \\ \hline $v_2$ & $x = (0, 1)$ \\ \hline \end{tabular} \caption{Vertex coordinates of the reference triangle.} \label{tab:triangle,vertices} \end{center} \end{table} \section{The reference quadrilateral} \index{quadrilateral} The reference quadrilateral is shown in Figure~\ref{fig:quadrilateral} and is defined by its four vertices with coordinates as specified in Table~\ref{tab:quadrilateral,vertices}. \begin{figure} \begin{center} \psfrag{v0}{$(0, 0)$} \psfrag{v1}{$(1, 0)$} \psfrag{v2}{$(1, 1)$} \psfrag{v3}{$(0, 1)$} \includegraphics[width=8cm]{eps/quadrilateral.eps} \caption{The reference quadrilateral.} \label{fig:quadrilateral} \end{center} \end{figure} \begin{table} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|c|c|} \hline Vertex & Coordinate \\ \hline \hline $v_0$ & $x = (0, 0)$ \\ \hline $v_1$ & $x = (1, 0)$ \\ \hline $v_2$ & $x = (1, 1)$ \\ \hline $v_3$ & $x = (0, 1)$ \\ \hline \end{tabular} \caption{Vertex coordinates of the reference quadrilateral.} \label{tab:quadrilateral,vertices} \end{center} \end{table} \section{The reference tetrahedron} \index{tetrahedron} The reference tetrahedron is shown in Figure~\ref{fig:tetrahedron} and is defined by its four vertices with coordinates as specified in Table~\ref{tab:tetrahedron,vertices}. \begin{figure} \begin{center} \psfrag{v0}{$(0, 0, 0)$} \psfrag{v1}{$(1, 0, 0)$} \psfrag{v2}{$(0, 1, 0)$} \psfrag{v3}{$(0, 0, 1)$} \includegraphics[width=6cm]{eps/tetrahedron.eps} \caption{The reference tetrahedron.} \label{fig:tetrahedron} \end{center} \end{figure} \begin{table} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|c|c|} \hline Vertex & Coordinate \\ \hline \hline $v_0$ & $x = (0, 0, 0)$ \\ \hline $v_1$ & $x = (1, 0, 0)$ \\ \hline $v_2$ & $x = (0, 1, 0)$ \\ \hline $v_3$ & $x = (0, 0, 1)$ \\ \hline \end{tabular} \caption{Vertex coordinates of the reference tetrahedron.} \label{tab:tetrahedron,vertices} \end{center} \end{table} \section{The reference hexahedron} \index{hexahedron} The reference hexahedron is shown in Figure~\ref{fig:hexahedron} and is defined by its eight vertices with coordinates as specified in Table~\ref{tab:hexahedron,vertices}. \begin{figure} \linespread{1.2}\selectfont \begin{center} \psfrag{v0}{$(0, 0, 0)$} \psfrag{v1}{$(1, 0, 0)$} \psfrag{v2}{$(1, 1, 0)$} \psfrag{v3}{$(0, 1, 0)$} \psfrag{v4}{$(0, 0, 1)$} \psfrag{v5}{$(1, 0, 1)$} \psfrag{v6}{$(1, 1, 1)$} \psfrag{v7}{$(0, 1, 1)$} \includegraphics[width=9cm]{eps/hexahedron.eps} \caption{The reference hexahedron.} \label{fig:hexahedron} \end{center} \end{figure} \begin{table} \linespread{1.2}\selectfont \begin{center} \begin{tabular}{|c|c|} \hline Vertex & Coordinate \\ \hline \hline $v_0$ & $x = (0, 0, 0)$ \\ \hline $v_1$ & $x = (1, 0, 0)$ \\ \hline $v_2$ & $x = (1, 1, 0)$ \\ \hline $v_3$ & $x = (0, 1, 0)$ \\ \hline \end{tabular} \begin{tabular}{|c|c|} \hline Vertex & Coordinate \\ \hline \hline $v_4$ & $x = (0, 0, 1)$ \\ \hline $v_5$ & $x = (1, 0, 1)$ \\ \hline $v_6$ & $x = (1, 1, 1)$ \\ \hline $v_7$ & $x = (0, 1, 1)$ \\ \hline \end{tabular} \caption{Vertex coordinates of the reference hexahedron.} \label{tab:hexahedron,vertices} \end{center} \end{table} ufc-2.3.0/doc/manual/chapters/versions.tex000066400000000000000000000055311226277264200205340ustar00rootroot00000000000000\chapter{\ufc{} versions} \label{app:versions} \index{versions} To keep things simple, the UFC classes do not have any run time version control. To upgrade to a new UFC version, all libraries and applications must therefore be recompiled with the new header file \texttt{ufc.h}. \section{Version 1.0} Initial release. \section{Version 1.1} The following six functions have been added to the interface: \begin{itemize} \item \texttt{ufc::finite\_element::evaluate\_dofs} \item \texttt{ufc::finite\_element::evaluate\_basis\_all} \item \texttt{ufc::finite\_element::evaluate\_basis\_derivatives\_all} \item \texttt{ufc::dof\_map::geometric\_dimension} \item \texttt{ufc::dof\_map::num\_entity\_dofs} \item \texttt{ufc::dof\_map::tabulate\_entity\_dofs} \end{itemize} An implementation of UFC version 1.0 can be recompiled with the header file from UFC version 1.1 without changes to the source code. The new functions introduced in 1.1 will then simply throw an informative exception. (The new functions are virtual but not pure virtual.) \section{Version 1.2} The following functions have been modified: \begin{itemize} \item \texttt{ufc::dof\_map::local\_dimension} \end{itemize} The following functions have been added to the interface: \begin{itemize} \item \texttt{ufc::dof\_map::max\_local\_dimension} \end{itemize} \section{Version 1.4} The behavior of the functions \texttt{ufc::form::create\_cell\_integral}, \texttt{ufc::form::create\_exterior\_facet\_integral} and \texttt{ufc::form::create\_interior\_facet\_integral} were changed to return a zero pointer when there is no integral on the given domain. \section{Version 2.0} The following names have been changed: \begin{itemize} \item \texttt{ufc::dof\_map} $\rightarrow$ \texttt{ufc::dofmap} \item \texttt{ufc::form::num\_cell\_integrals} $\rightarrow$ \texttt{ufc::form::num\_cell\_domains} \item \texttt{ufc::form::num\_exterior\_facet\_integrals} $\rightarrow$ \texttt{ufc::form::num\_exterior\_facet\_domains} \item \texttt{ufc::form::num\_interior\_facet\_integrals} $\rightarrow$ \texttt{ufc::form::num\_interior\_facet\_domains} \end{itemize} The following new data members have been added: \begin{itemize} \item \texttt{ufc::cell:index} \item \texttt{ufc::cell:local\_facet} \item \texttt{ufc::cell:mesh\_identifier} \end{itemize} The following new functions have been added: \begin{itemize} \item \texttt{ufc::finite\_element::topological\_dimension} \item \texttt{ufc::finite\_element::geometric\_dimension} \item \texttt{ufc::finite\_element::create} \item \texttt{ufc::dofmap::topological\_dimension} \item \texttt{ufc::dofmap::create} \item \texttt{ufc::cell\_integral::tabulate\_tensor} (quadrature version) \item \texttt{ufc::exterior\_facet\_integral::tabulate\_tensor} (quadrature version) \item \texttt{ufc::interior\_integral::tabulate\_tensor} (quadrature version) \end{itemize} ufc-2.3.0/doc/manual/code/000077500000000000000000000000001226277264200152375ustar00rootroot00000000000000ufc-2.3.0/doc/manual/code/Poisson.ufl000066400000000000000000000006061226277264200174030ustar00rootroot00000000000000# Copyright (C) 2004-2007 Anders Logg (logg@simula.no) # Licensed under the GNU GPL Version 2 # # The bilinear form a(v, u) and linear form L(v) for # Poisson's equation. # # Compile this form with FFC: ffc Poisson.form element = FiniteElement("Lagrange", "triangle", 1) v = TestFunction(element) u = TrialFunction(element) f = Function(element) a = dot(grad(v), grad(u))*dx #L = v*f*dx ufc-2.3.0/doc/manual/code/poisson_ffc.h000066400000000000000000001257241226277264200177330ustar00rootroot00000000000000// This code conforms with the UFC specification version 1.0 // and was automatically generated by FFC version 0.6.2. #ifndef __POISSON_H #define __POISSON_H #include #include #include /// This class defines the interface for a finite element. class PoissonBilinearForm_finite_element_0: public ufc::finite_element { public: /// Constructor PoissonBilinearForm_finite_element_0() : ufc::finite_element() { // Do nothing } /// Destructor virtual ~PoissonBilinearForm_finite_element_0() { // Do nothing } /// Return a string identifying the finite element virtual const char* signature() const { return "FiniteElement('Lagrange', 'triangle', 1)"; } /// Return the cell shape virtual ufc::shape cell_shape() const { return ufc::triangle; } /// Return the dimension of the finite element function space virtual unsigned int space_dimension() const { return 3; } /// Return the rank of the value space virtual unsigned int value_rank() const { return 0; } /// Return the dimension of the value space for axis i virtual unsigned int value_dimension(unsigned int i) const { return 1; } /// Evaluate basis function i at given point in cell virtual void evaluate_basis(unsigned int i, double* values, const double* coordinates, const ufc::cell& c) const { // Extract vertex coordinates const double * const * element_coordinates = c.coordinates; // Compute Jacobian of affine map from reference cell const double J_00 = element_coordinates[1][0] - element_coordinates[0][0]; const double J_01 = element_coordinates[2][0] - element_coordinates[0][0]; const double J_10 = element_coordinates[1][1] - element_coordinates[0][1]; const double J_11 = element_coordinates[2][1] - element_coordinates[0][1]; // Compute determinant of Jacobian const double detJ = J_00*J_11 - J_01*J_10; // Compute inverse of Jacobian // Get coordinates and map to the reference (UFC) element double x = (element_coordinates[0][1]*element_coordinates[2][0] -\ element_coordinates[0][0]*element_coordinates[2][1] +\ J_11*coordinates[0] - J_01*coordinates[1]) / detJ; double y = (element_coordinates[1][1]*element_coordinates[0][0] -\ element_coordinates[1][0]*element_coordinates[0][1] -\ J_10*coordinates[0] + J_00*coordinates[1]) / detJ; // Map coordinates to the reference square if (std::abs(y - 1.0) < 1e-14) x = -1.0; else x = 2.0 *x/(1.0 - y) - 1.0; y = 2.0*y - 1.0; // Reset values *values = 0; // Map degree of freedom to element degree of freedom const unsigned int dof = i; // Generate scalings const double scalings_y_0 = 1; const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y); // Compute psitilde_a const double psitilde_a_0 = 1; const double psitilde_a_1 = x; // Compute psitilde_bs const double psitilde_bs_0_0 = 1; const double psitilde_bs_0_1 = 1.5*y + 0.5; const double psitilde_bs_1_0 = 1; // Compute basisvalues const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0; const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0; const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1; // Table(s) of coefficients const static double coefficients0[3][3] = \ {{0.471404520791032, -0.288675134594813, -0.166666666666667}, {0.471404520791032, 0.288675134594813, -0.166666666666667}, {0.471404520791032, 0, 0.333333333333333}}; // Extract relevant coefficients const double coeff0_0 = coefficients0[dof][0]; const double coeff0_1 = coefficients0[dof][1]; const double coeff0_2 = coefficients0[dof][2]; // Compute value(s) *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2; } /// Evaluate all basis functions at given point in cell virtual void evaluate_basis_all(double* values, const double* coordinates, const ufc::cell& c) const { throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented."); } /// Evaluate order n derivatives of basis function i at given point in cell virtual void evaluate_basis_derivatives(unsigned int i, unsigned int n, double* values, const double* coordinates, const ufc::cell& c) const { // Extract vertex coordinates const double * const * element_coordinates = c.coordinates; // Compute Jacobian of affine map from reference cell const double J_00 = element_coordinates[1][0] - element_coordinates[0][0]; const double J_01 = element_coordinates[2][0] - element_coordinates[0][0]; const double J_10 = element_coordinates[1][1] - element_coordinates[0][1]; const double J_11 = element_coordinates[2][1] - element_coordinates[0][1]; // Compute determinant of Jacobian const double detJ = J_00*J_11 - J_01*J_10; // Compute inverse of Jacobian // Get coordinates and map to the reference (UFC) element double x = (element_coordinates[0][1]*element_coordinates[2][0] -\ element_coordinates[0][0]*element_coordinates[2][1] +\ J_11*coordinates[0] - J_01*coordinates[1]) / detJ; double y = (element_coordinates[1][1]*element_coordinates[0][0] -\ element_coordinates[1][0]*element_coordinates[0][1] -\ J_10*coordinates[0] + J_00*coordinates[1]) / detJ; // Map coordinates to the reference square if (std::abs(y - 1.0) < 1e-14) x = -1.0; else x = 2.0 *x/(1.0 - y) - 1.0; y = 2.0*y - 1.0; // Compute number of derivatives unsigned int num_derivatives = 1; for (unsigned int j = 0; j < n; j++) num_derivatives *= 2; // Declare pointer to two dimensional array that holds combinations of derivatives and initialise unsigned int **combinations = new unsigned int *[num_derivatives]; for (unsigned int j = 0; j < num_derivatives; j++) { combinations[j] = new unsigned int [n]; for (unsigned int k = 0; k < n; k++) combinations[j][k] = 0; } // Generate combinations of derivatives for (unsigned int row = 1; row < num_derivatives; row++) { for (unsigned int num = 0; num < row; num++) { for (unsigned int col = n-1; col+1 > 0; col--) { if (combinations[row][col] + 1 > 1) combinations[row][col] = 0; else { combinations[row][col] += 1; break; } } } } // Compute inverse of Jacobian const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, J_00 / detJ}}; // Declare transformation matrix // Declare pointer to two dimensional array and initialise double **transform = new double *[num_derivatives]; for (unsigned int j = 0; j < num_derivatives; j++) { transform[j] = new double [num_derivatives]; for (unsigned int k = 0; k < num_derivatives; k++) transform[j][k] = 1; } // Construct transformation matrix for (unsigned int row = 0; row < num_derivatives; row++) { for (unsigned int col = 0; col < num_derivatives; col++) { for (unsigned int k = 0; k < n; k++) transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]]; } } // Reset values for (unsigned int j = 0; j < 1*num_derivatives; j++) values[j] = 0; // Map degree of freedom to element degree of freedom const unsigned int dof = i; // Generate scalings const double scalings_y_0 = 1; const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y); // Compute psitilde_a const double psitilde_a_0 = 1; const double psitilde_a_1 = x; // Compute psitilde_bs const double psitilde_bs_0_0 = 1; const double psitilde_bs_0_1 = 1.5*y + 0.5; const double psitilde_bs_1_0 = 1; // Compute basisvalues const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0; const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0; const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1; // Table(s) of coefficients const static double coefficients0[3][3] = \ {{0.471404520791032, -0.288675134594813, -0.166666666666667}, {0.471404520791032, 0.288675134594813, -0.166666666666667}, {0.471404520791032, 0, 0.333333333333333}}; // Interesting (new) part // Tables of derivatives of the polynomial base (transpose) const static double dmats0[3][3] = \ {{0, 0, 0}, {4.89897948556636, 0, 0}, {0, 0, 0}}; const static double dmats1[3][3] = \ {{0, 0, 0}, {2.44948974278318, 0, 0}, {4.24264068711928, 0, 0}}; // Compute reference derivatives // Declare pointer to array of derivatives on FIAT element double *derivatives = new double [num_derivatives]; // Declare coefficients double coeff0_0 = 0; double coeff0_1 = 0; double coeff0_2 = 0; // Declare new coefficients double new_coeff0_0 = 0; double new_coeff0_1 = 0; double new_coeff0_2 = 0; // Loop possible derivatives for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++) { // Get values from coefficients array new_coeff0_0 = coefficients0[dof][0]; new_coeff0_1 = coefficients0[dof][1]; new_coeff0_2 = coefficients0[dof][2]; // Loop derivative order for (unsigned int j = 0; j < n; j++) { // Update old coefficients coeff0_0 = new_coeff0_0; coeff0_1 = new_coeff0_1; coeff0_2 = new_coeff0_2; if(combinations[deriv_num][j] == 0) { new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0]; new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1]; new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2]; } if(combinations[deriv_num][j] == 1) { new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0]; new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1]; new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2]; } } // Compute derivatives on reference element as dot product of coefficients and basisvalues derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2; } // Transform derivatives back to physical element for (unsigned int row = 0; row < num_derivatives; row++) { for (unsigned int col = 0; col < num_derivatives; col++) { values[row] += transform[row][col]*derivatives[col]; } } // Delete pointer to array of derivatives on FIAT element delete [] derivatives; // Delete pointer to array of combinations of derivatives and transform for (unsigned int row = 0; row < num_derivatives; row++) { delete [] combinations[row]; delete [] transform[row]; } delete [] combinations; delete [] transform; } /// Evaluate order n derivatives of all basis functions at given point in cell virtual void evaluate_basis_derivatives_all(unsigned int n, double* values, const double* coordinates, const ufc::cell& c) const { throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented."); } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(unsigned int i, const ufc::function& f, const ufc::cell& c) const { // The reference points, direction and weights: const static double X[3][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}}; const static double W[3][1] = {{1}, {1}, {1}}; const static double D[3][1][1] = {{{1}}, {{1}}, {{1}}}; const double * const * x = c.coordinates; double result = 0.0; // Iterate over the points: // Evaluate basis functions for affine mapping const double w0 = 1.0 - X[i][0][0] - X[i][0][1]; const double w1 = X[i][0][0]; const double w2 = X[i][0][1]; // Compute affine mapping y = F(X) double y[2]; y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0]; y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1]; // Evaluate function at physical points double values[1]; f.evaluate(values, y, c); // Map function values using appropriate mapping // Affine map: Do nothing // Note that we do not map the weights (yet). // Take directional components for(int k = 0; k < 1; k++) result += values[k]*D[i][0][k]; // Multiply by weights result *= W[i][0]; return result; } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const ufc::cell& c) const { throw std::runtime_error("Not implemented (introduced in UFC v1.1)."); } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const ufc::cell& c) const { // Evaluate at vertices and use affine mapping vertex_values[0] = dof_values[0]; vertex_values[1] = dof_values[1]; vertex_values[2] = dof_values[2]; } /// Return the number of sub elements (for a mixed element) virtual unsigned int num_sub_elements() const { return 1; } /// Create a new finite element for sub element i (for a mixed element) virtual ufc::finite_element* create_sub_element(unsigned int i) const { return new PoissonBilinearForm_finite_element_0(); } }; /// This class defines the interface for a finite element. class PoissonBilinearForm_finite_element_1: public ufc::finite_element { public: /// Constructor PoissonBilinearForm_finite_element_1() : ufc::finite_element() { // Do nothing } /// Destructor virtual ~PoissonBilinearForm_finite_element_1() { // Do nothing } /// Return a string identifying the finite element virtual const char* signature() const { return "FiniteElement('Lagrange', 'triangle', 1)"; } /// Return the cell shape virtual ufc::shape cell_shape() const { return ufc::triangle; } /// Return the dimension of the finite element function space virtual unsigned int space_dimension() const { return 3; } /// Return the rank of the value space virtual unsigned int value_rank() const { return 0; } /// Return the dimension of the value space for axis i virtual unsigned int value_dimension(unsigned int i) const { return 1; } /// Evaluate basis function i at given point in cell virtual void evaluate_basis(unsigned int i, double* values, const double* coordinates, const ufc::cell& c) const { // Extract vertex coordinates const double * const * element_coordinates = c.coordinates; // Compute Jacobian of affine map from reference cell const double J_00 = element_coordinates[1][0] - element_coordinates[0][0]; const double J_01 = element_coordinates[2][0] - element_coordinates[0][0]; const double J_10 = element_coordinates[1][1] - element_coordinates[0][1]; const double J_11 = element_coordinates[2][1] - element_coordinates[0][1]; // Compute determinant of Jacobian const double detJ = J_00*J_11 - J_01*J_10; // Compute inverse of Jacobian // Get coordinates and map to the reference (UFC) element double x = (element_coordinates[0][1]*element_coordinates[2][0] -\ element_coordinates[0][0]*element_coordinates[2][1] +\ J_11*coordinates[0] - J_01*coordinates[1]) / detJ; double y = (element_coordinates[1][1]*element_coordinates[0][0] -\ element_coordinates[1][0]*element_coordinates[0][1] -\ J_10*coordinates[0] + J_00*coordinates[1]) / detJ; // Map coordinates to the reference square if (std::abs(y - 1.0) < 1e-14) x = -1.0; else x = 2.0 *x/(1.0 - y) - 1.0; y = 2.0*y - 1.0; // Reset values *values = 0; // Map degree of freedom to element degree of freedom const unsigned int dof = i; // Generate scalings const double scalings_y_0 = 1; const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y); // Compute psitilde_a const double psitilde_a_0 = 1; const double psitilde_a_1 = x; // Compute psitilde_bs const double psitilde_bs_0_0 = 1; const double psitilde_bs_0_1 = 1.5*y + 0.5; const double psitilde_bs_1_0 = 1; // Compute basisvalues const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0; const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0; const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1; // Table(s) of coefficients const static double coefficients0[3][3] = \ {{0.471404520791032, -0.288675134594813, -0.166666666666667}, {0.471404520791032, 0.288675134594813, -0.166666666666667}, {0.471404520791032, 0, 0.333333333333333}}; // Extract relevant coefficients const double coeff0_0 = coefficients0[dof][0]; const double coeff0_1 = coefficients0[dof][1]; const double coeff0_2 = coefficients0[dof][2]; // Compute value(s) *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2; } /// Evaluate all basis functions at given point in cell virtual void evaluate_basis_all(double* values, const double* coordinates, const ufc::cell& c) const { throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented."); } /// Evaluate order n derivatives of basis function i at given point in cell virtual void evaluate_basis_derivatives(unsigned int i, unsigned int n, double* values, const double* coordinates, const ufc::cell& c) const { // Extract vertex coordinates const double * const * element_coordinates = c.coordinates; // Compute Jacobian of affine map from reference cell const double J_00 = element_coordinates[1][0] - element_coordinates[0][0]; const double J_01 = element_coordinates[2][0] - element_coordinates[0][0]; const double J_10 = element_coordinates[1][1] - element_coordinates[0][1]; const double J_11 = element_coordinates[2][1] - element_coordinates[0][1]; // Compute determinant of Jacobian const double detJ = J_00*J_11 - J_01*J_10; // Compute inverse of Jacobian // Get coordinates and map to the reference (UFC) element double x = (element_coordinates[0][1]*element_coordinates[2][0] -\ element_coordinates[0][0]*element_coordinates[2][1] +\ J_11*coordinates[0] - J_01*coordinates[1]) / detJ; double y = (element_coordinates[1][1]*element_coordinates[0][0] -\ element_coordinates[1][0]*element_coordinates[0][1] -\ J_10*coordinates[0] + J_00*coordinates[1]) / detJ; // Map coordinates to the reference square if (std::abs(y - 1.0) < 1e-14) x = -1.0; else x = 2.0 *x/(1.0 - y) - 1.0; y = 2.0*y - 1.0; // Compute number of derivatives unsigned int num_derivatives = 1; for (unsigned int j = 0; j < n; j++) num_derivatives *= 2; // Declare pointer to two dimensional array that holds combinations of derivatives and initialise unsigned int **combinations = new unsigned int *[num_derivatives]; for (unsigned int j = 0; j < num_derivatives; j++) { combinations[j] = new unsigned int [n]; for (unsigned int k = 0; k < n; k++) combinations[j][k] = 0; } // Generate combinations of derivatives for (unsigned int row = 1; row < num_derivatives; row++) { for (unsigned int num = 0; num < row; num++) { for (unsigned int col = n-1; col+1 > 0; col--) { if (combinations[row][col] + 1 > 1) combinations[row][col] = 0; else { combinations[row][col] += 1; break; } } } } // Compute inverse of Jacobian const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, J_00 / detJ}}; // Declare transformation matrix // Declare pointer to two dimensional array and initialise double **transform = new double *[num_derivatives]; for (unsigned int j = 0; j < num_derivatives; j++) { transform[j] = new double [num_derivatives]; for (unsigned int k = 0; k < num_derivatives; k++) transform[j][k] = 1; } // Construct transformation matrix for (unsigned int row = 0; row < num_derivatives; row++) { for (unsigned int col = 0; col < num_derivatives; col++) { for (unsigned int k = 0; k < n; k++) transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]]; } } // Reset values for (unsigned int j = 0; j < 1*num_derivatives; j++) values[j] = 0; // Map degree of freedom to element degree of freedom const unsigned int dof = i; // Generate scalings const double scalings_y_0 = 1; const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y); // Compute psitilde_a const double psitilde_a_0 = 1; const double psitilde_a_1 = x; // Compute psitilde_bs const double psitilde_bs_0_0 = 1; const double psitilde_bs_0_1 = 1.5*y + 0.5; const double psitilde_bs_1_0 = 1; // Compute basisvalues const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0; const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0; const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1; // Table(s) of coefficients const static double coefficients0[3][3] = \ {{0.471404520791032, -0.288675134594813, -0.166666666666667}, {0.471404520791032, 0.288675134594813, -0.166666666666667}, {0.471404520791032, 0, 0.333333333333333}}; // Interesting (new) part // Tables of derivatives of the polynomial base (transpose) const static double dmats0[3][3] = \ {{0, 0, 0}, {4.89897948556636, 0, 0}, {0, 0, 0}}; const static double dmats1[3][3] = \ {{0, 0, 0}, {2.44948974278318, 0, 0}, {4.24264068711928, 0, 0}}; // Compute reference derivatives // Declare pointer to array of derivatives on FIAT element double *derivatives = new double [num_derivatives]; // Declare coefficients double coeff0_0 = 0; double coeff0_1 = 0; double coeff0_2 = 0; // Declare new coefficients double new_coeff0_0 = 0; double new_coeff0_1 = 0; double new_coeff0_2 = 0; // Loop possible derivatives for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++) { // Get values from coefficients array new_coeff0_0 = coefficients0[dof][0]; new_coeff0_1 = coefficients0[dof][1]; new_coeff0_2 = coefficients0[dof][2]; // Loop derivative order for (unsigned int j = 0; j < n; j++) { // Update old coefficients coeff0_0 = new_coeff0_0; coeff0_1 = new_coeff0_1; coeff0_2 = new_coeff0_2; if(combinations[deriv_num][j] == 0) { new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0]; new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1]; new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2]; } if(combinations[deriv_num][j] == 1) { new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0]; new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1]; new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2]; } } // Compute derivatives on reference element as dot product of coefficients and basisvalues derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2; } // Transform derivatives back to physical element for (unsigned int row = 0; row < num_derivatives; row++) { for (unsigned int col = 0; col < num_derivatives; col++) { values[row] += transform[row][col]*derivatives[col]; } } // Delete pointer to array of derivatives on FIAT element delete [] derivatives; // Delete pointer to array of combinations of derivatives and transform for (unsigned int row = 0; row < num_derivatives; row++) { delete [] combinations[row]; delete [] transform[row]; } delete [] combinations; delete [] transform; } /// Evaluate order n derivatives of all basis functions at given point in cell virtual void evaluate_basis_derivatives_all(unsigned int n, double* values, const double* coordinates, const ufc::cell& c) const { throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented."); } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(unsigned int i, const ufc::function& f, const ufc::cell& c) const { // The reference points, direction and weights: const static double X[3][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}}; const static double W[3][1] = {{1}, {1}, {1}}; const static double D[3][1][1] = {{{1}}, {{1}}, {{1}}}; const double * const * x = c.coordinates; double result = 0.0; // Iterate over the points: // Evaluate basis functions for affine mapping const double w0 = 1.0 - X[i][0][0] - X[i][0][1]; const double w1 = X[i][0][0]; const double w2 = X[i][0][1]; // Compute affine mapping y = F(X) double y[2]; y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0]; y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1]; // Evaluate function at physical points double values[1]; f.evaluate(values, y, c); // Map function values using appropriate mapping // Affine map: Do nothing // Note that we do not map the weights (yet). // Take directional components for(int k = 0; k < 1; k++) result += values[k]*D[i][0][k]; // Multiply by weights result *= W[i][0]; return result; } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const ufc::cell& c) const { throw std::runtime_error("Not implemented (introduced in UFC v1.1)."); } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const ufc::cell& c) const { // Evaluate at vertices and use affine mapping vertex_values[0] = dof_values[0]; vertex_values[1] = dof_values[1]; vertex_values[2] = dof_values[2]; } /// Return the number of sub elements (for a mixed element) virtual unsigned int num_sub_elements() const { return 1; } /// Create a new finite element for sub element i (for a mixed element) virtual ufc::finite_element* create_sub_element(unsigned int i) const { return new PoissonBilinearForm_finite_element_1(); } }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class PoissonBilinearForm_dof_map_0: public ufc::dof_map { private: unsigned int __global_dimension; public: /// Constructor PoissonBilinearForm_dof_map_0() : ufc::dof_map() { __global_dimension = 0; } /// Destructor virtual ~PoissonBilinearForm_dof_map_0() { // Do nothing } /// Return a string identifying the dof map virtual const char* signature() const { return "FFC dof map for FiniteElement('Lagrange', 'triangle', 1)"; } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(unsigned int d) const { switch (d) { case 0: return true; break; case 1: return false; break; case 2: return false; break; } return false; } /// Initialize dof map for mesh (return true iff init_cell() is needed) virtual bool init_mesh(const ufc::mesh& m) { __global_dimension = m.num_entities[0]; return false; } /// Initialize dof map for given cell virtual void init_cell(const ufc::mesh& m, const ufc::cell& c) { // Do nothing } /// Finish initialization of dof map for cells virtual void init_cell_finalize() { // Do nothing } /// Return the dimension of the global finite element function space virtual unsigned int global_dimension() const { return __global_dimension; } /// Return the dimension of the local finite element function space virtual unsigned int local_dimension() const { return 3; } // Return the geometric dimension of the coordinates this dof map provides virtual unsigned int geometric_dimension() const { return 2; } /// Return the number of dofs on each cell facet virtual unsigned int num_facet_dofs() const { return 2; } /// Return the number of dofs associated with each cell entity of dimension d virtual unsigned int num_entity_dofs(unsigned int d) const { throw std::runtime_error("Not implemented (introduced in UFC v1.1)."); } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(unsigned int* dofs, const ufc::mesh& m, const ufc::cell& c) const { dofs[0] = c.entity_indices[0][0]; dofs[1] = c.entity_indices[0][1]; dofs[2] = c.entity_indices[0][2]; } /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(unsigned int* dofs, unsigned int facet) const { switch (facet) { case 0: dofs[0] = 1; dofs[1] = 2; break; case 1: dofs[0] = 0; dofs[1] = 2; break; case 2: dofs[0] = 0; dofs[1] = 1; break; } } /// Tabulate the local-to-local mapping of dofs on entity (d, i) virtual void tabulate_entity_dofs(unsigned int* dofs, unsigned int d, unsigned int i) const { throw std::runtime_error("Not implemented (introduced in UFC v1.1)."); } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double** coordinates, const ufc::cell& c) const { const double * const * x = c.coordinates; coordinates[0][0] = x[0][0]; coordinates[0][1] = x[0][1]; coordinates[1][0] = x[1][0]; coordinates[1][1] = x[1][1]; coordinates[2][0] = x[2][0]; coordinates[2][1] = x[2][1]; } /// Return the number of sub dof maps (for a mixed element) virtual unsigned int num_sub_dof_maps() const { return 1; } /// Create a new dof_map for sub dof map i (for a mixed element) virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const { return new PoissonBilinearForm_dof_map_0(); } }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class PoissonBilinearForm_dof_map_1: public ufc::dof_map { private: unsigned int __global_dimension; public: /// Constructor PoissonBilinearForm_dof_map_1() : ufc::dof_map() { __global_dimension = 0; } /// Destructor virtual ~PoissonBilinearForm_dof_map_1() { // Do nothing } /// Return a string identifying the dof map virtual const char* signature() const { return "FFC dof map for FiniteElement('Lagrange', 'triangle', 1)"; } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(unsigned int d) const { switch (d) { case 0: return true; break; case 1: return false; break; case 2: return false; break; } return false; } /// Initialize dof map for mesh (return true iff init_cell() is needed) virtual bool init_mesh(const ufc::mesh& m) { __global_dimension = m.num_entities[0]; return false; } /// Initialize dof map for given cell virtual void init_cell(const ufc::mesh& m, const ufc::cell& c) { // Do nothing } /// Finish initialization of dof map for cells virtual void init_cell_finalize() { // Do nothing } /// Return the dimension of the global finite element function space virtual unsigned int global_dimension() const { return __global_dimension; } /// Return the dimension of the local finite element function space virtual unsigned int local_dimension() const { return 3; } // Return the geometric dimension of the coordinates this dof map provides virtual unsigned int geometric_dimension() const { return 2; } /// Return the number of dofs on each cell facet virtual unsigned int num_facet_dofs() const { return 2; } /// Return the number of dofs associated with each cell entity of dimension d virtual unsigned int num_entity_dofs(unsigned int d) const { throw std::runtime_error("Not implemented (introduced in UFC v1.1)."); } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(unsigned int* dofs, const ufc::mesh& m, const ufc::cell& c) const { dofs[0] = c.entity_indices[0][0]; dofs[1] = c.entity_indices[0][1]; dofs[2] = c.entity_indices[0][2]; } /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(unsigned int* dofs, unsigned int facet) const { switch (facet) { case 0: dofs[0] = 1; dofs[1] = 2; break; case 1: dofs[0] = 0; dofs[1] = 2; break; case 2: dofs[0] = 0; dofs[1] = 1; break; } } /// Tabulate the local-to-local mapping of dofs on entity (d, i) virtual void tabulate_entity_dofs(unsigned int* dofs, unsigned int d, unsigned int i) const { throw std::runtime_error("Not implemented (introduced in UFC v1.1)."); } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double** coordinates, const ufc::cell& c) const { const double * const * x = c.coordinates; coordinates[0][0] = x[0][0]; coordinates[0][1] = x[0][1]; coordinates[1][0] = x[1][0]; coordinates[1][1] = x[1][1]; coordinates[2][0] = x[2][0]; coordinates[2][1] = x[2][1]; } /// Return the number of sub dof maps (for a mixed element) virtual unsigned int num_sub_dof_maps() const { return 1; } /// Create a new dof_map for sub dof map i (for a mixed element) virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const { return new PoissonBilinearForm_dof_map_1(); } }; /// This class defines the interface for the tabulation of the cell /// tensor corresponding to the local contribution to a form from /// the integral over a cell. class PoissonBilinearForm_cell_integral_0_quadrature: public ufc::cell_integral { public: /// Constructor PoissonBilinearForm_cell_integral_0_quadrature() : ufc::cell_integral() { // Do nothing } /// Destructor virtual ~PoissonBilinearForm_cell_integral_0_quadrature() { // Do nothing } /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor(double* A, const double * const * w, const ufc::cell& c) const { // Extract vertex coordinates const double * const * x = c.coordinates; // Compute Jacobian of affine map from reference cell const double J_00 = x[1][0] - x[0][0]; const double J_01 = x[2][0] - x[0][0]; const double J_10 = x[1][1] - x[0][1]; const double J_11 = x[2][1] - x[0][1]; // Compute determinant of Jacobian double detJ = J_00*J_11 - J_01*J_10; // Compute inverse of Jacobian const double Jinv_00 = J_11 / detJ; const double Jinv_01 = -J_01 / detJ; const double Jinv_10 = -J_10 / detJ; const double Jinv_11 = J_00 / detJ; // Set scale factor const double det = std::abs(detJ); // Array of quadrature weights const static double W1 = 0.5; const static double FE0_D10[1][3] = \ {{-1, 1, 0}}; const static double FE0_D01[1][3] = \ {{-1, 0, 1}}; // Compute element tensor using UFL quadrature representation // Optimisations: ('simplify expressions', False), ('ignore zero tables', False), ('non zero columns', False), ('remove zero terms', False), ('ignore ones', False) // Total number of operations to compute element tensor: 162 // Loop quadrature points for integral // Number of operations to compute element tensor for following IP loop = 162 // Only 1 integration point, omitting IP loop. // Number of operations for primary indices = 162 for (unsigned int j = 0; j < 3; j++) { for (unsigned int k = 0; k < 3; k++) { // Number of operations to compute entry = 18 A[j*3 + k] += ((Jinv_00*FE0_D10[0][j] + Jinv_10*FE0_D01[0][j])*(Jinv_00*FE0_D10[0][k] + Jinv_10*FE0_D01[0][k]) + (Jinv_01*FE0_D10[0][j] + Jinv_11*FE0_D01[0][j])*(Jinv_01*FE0_D10[0][k] + Jinv_11*FE0_D01[0][k]))*W1*det; }// end loop over 'k' }// end loop over 'j' } }; /// This class defines the interface for the tabulation of the cell /// tensor corresponding to the local contribution to a form from /// the integral over a cell. class PoissonBilinearForm_cell_integral_0: public ufc::cell_integral { private: PoissonBilinearForm_cell_integral_0_quadrature integral_0_quadrature; public: /// Constructor PoissonBilinearForm_cell_integral_0() : ufc::cell_integral() { // Do nothing } /// Destructor virtual ~PoissonBilinearForm_cell_integral_0() { // Do nothing } /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor(double* A, const double * const * w, const ufc::cell& c) const { // Reset values of the element tensor block A[0] = 0; A[1] = 0; A[2] = 0; A[3] = 0; A[4] = 0; A[5] = 0; A[6] = 0; A[7] = 0; A[8] = 0; // Add all contributions to element tensor integral_0_quadrature.tabulate_tensor(A, w, c); } }; /// This class defines the interface for the assembly of the global /// tensor corresponding to a form with r + n arguments, that is, a /// mapping /// /// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R /// /// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r /// global tensor A is defined by /// /// A = a(V1, V2, ..., Vr, w1, w2, ..., wn), /// /// where each argument Vj represents the application to the /// sequence of basis functions of Vj and w1, w2, ..., wn are given /// fixed functions (coefficients). class PoissonBilinearForm: public ufc::form { public: /// Constructor PoissonBilinearForm() : ufc::form() { // Do nothing } /// Destructor virtual ~PoissonBilinearForm() { // Do nothing } /// Return a string identifying the form virtual const char* signature() const { return "Form([Integral(IndexSum(Product(Indexed(ComponentTensor(SpatialDerivative(BasisFunction(FiniteElement('Lagrange', Cell('triangle', 1), 1), 0), MultiIndex((Index(0),), {Index(0): 2})), MultiIndex((Index(0),), {Index(0): 2})), MultiIndex((Index(1),), {Index(1): 2})), Indexed(ComponentTensor(SpatialDerivative(BasisFunction(FiniteElement('Lagrange', Cell('triangle', 1), 1), 1), MultiIndex((Index(2),), {Index(2): 2})), MultiIndex((Index(2),), {Index(2): 2})), MultiIndex((Index(1),), {Index(1): 2}))), MultiIndex((Index(1),), {Index(1): 2})), Measure('cell', 0, None))])"; } /// Return the rank of the global tensor (r) virtual unsigned int rank() const { return 2; } /// Return the number of coefficients (n) virtual unsigned int num_coefficients() const { return 0; } /// Return the number of cell integrals virtual unsigned int num_cell_integrals() const { return 1; } /// Return the number of exterior facet integrals virtual unsigned int num_exterior_facet_integrals() const { return 0; } /// Return the number of interior facet integrals virtual unsigned int num_interior_facet_integrals() const { return 0; } /// Create a new finite element for argument function i virtual ufc::finite_element* create_finite_element(unsigned int i) const { switch (i) { case 0: return new PoissonBilinearForm_finite_element_0(); break; case 1: return new PoissonBilinearForm_finite_element_1(); break; } return 0; } /// Create a new dof map for argument function i virtual ufc::dof_map* create_dof_map(unsigned int i) const { switch (i) { case 0: return new PoissonBilinearForm_dof_map_0(); break; case 1: return new PoissonBilinearForm_dof_map_1(); break; } return 0; } /// Create a new cell integral on sub domain i virtual ufc::cell_integral* create_cell_integral(unsigned int i) const { return new PoissonBilinearForm_cell_integral_0(); } /// Create a new exterior facet integral on sub domain i virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const { return 0; } /// Create a new interior facet integral on sub domain i virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const { return 0; } }; #endif ufc-2.3.0/doc/manual/code/poisson_syfi.h000066400000000000000000000000241226277264200201300ustar00rootroot00000000000000// Add example here ufc-2.3.0/doc/manual/code/stiffness_syfi/000077500000000000000000000000001226277264200202755ustar00rootroot00000000000000ufc-2.3.0/doc/manual/code/stiffness_syfi/dof_map_Lagrange_1_2D.cpp000066400000000000000000000112521226277264200247540ustar00rootroot00000000000000// // This code complies with UFC version 1.0, and is generated with SyFi version 0.4.0. // // http://www.fenics.org/syfi/ // http://www.fenics.org/ufc/ // #include #include #include #include #include #include #include #include #include "dof_map_Lagrange_1_2D.h" namespace pycc { /// Constructor dof_map_Lagrange_1_2D::dof_map_Lagrange_1_2D() : ufc::dof_map() { loc2glob = 0; } /// Destructor dof_map_Lagrange_1_2D::~dof_map_Lagrange_1_2D() { if(loc2glob) delete [] loc2glob; } /// Return a string identifying the dof map const char* dof_map_Lagrange_1_2D::signature() const { return "dof_map_Lagrange_1_2D // generated by SyFi"; } /// Return true iff mesh entities of topological dimension d are needed bool dof_map_Lagrange_1_2D::needs_mesh_entities(unsigned int d) const { switch(d) { case 0: return true; // vertices case 1: return true; // edges case 2: return true; // faces case 3: return false; // volumes } return false; // strange unsupported case or error } /// Initialize dof map for mesh (return true iff init_cell() is needed) bool dof_map_Lagrange_1_2D::init_mesh(const ufc::mesh& m) { int top_dim = 2; num_elements = m.num_entities[top_dim]; return true; } /// Initialize dof map for given cell void dof_map_Lagrange_1_2D::init_cell(const ufc::mesh& m, const ufc::cell& c) { // coordinates double x0 = c.coordinates[0][0]; double y0 = c.coordinates[0][1]; double x1 = c.coordinates[1][0]; double y1 = c.coordinates[1][1]; double x2 = c.coordinates[2][0]; double y2 = c.coordinates[2][1]; // affine map double G00 = x1 - x0; double G01 = x2 - x0; double G10 = y1 - y0; double G11 = y2 - y0; int element = c.entity_indices[2][0]; double dof0[2] = { x0, y0 }; Ptv pdof0(2, dof0); dof.insert_dof(element, 0, pdof0); double dof1[2] = { G00+x0, y0+G10 }; Ptv pdof1(2, dof1); dof.insert_dof(element, 1, pdof1); double dof2[2] = { x0+G01, G11+y0 }; Ptv pdof2(2, dof2); dof.insert_dof(element, 2, pdof2); } /// Finish initialization of dof map for cells void dof_map_Lagrange_1_2D::init_cell_finalize() { loc2glob = new unsigned int[num_elements * local_dimension()]; dof.build_loc2dof(num_elements, local_dimension(), reinterpret_cast(loc2glob)); } /// Return the dimension of the global finite element function space unsigned int dof_map_Lagrange_1_2D::global_dimension() const { return dof.size(); } /// Return the dimension of the local finite element function space unsigned int dof_map_Lagrange_1_2D::local_dimension() const { return 3; } /// Return the number of dofs on each cell facet unsigned int dof_map_Lagrange_1_2D::num_facet_dofs() const { return 2; } /// Tabulate the local-to-global mapping of dofs on a cell void dof_map_Lagrange_1_2D::tabulate_dofs(unsigned int* dofs, const ufc::mesh& m, const ufc::cell& c) const { const unsigned int *from_dofs = loc2glob + (3 * c.entity_indices[2][0]); memcpy(dofs, from_dofs, sizeof(unsigned int)*3); } /// Tabulate the local-to-local mapping from facet dofs to cell dofs void dof_map_Lagrange_1_2D::tabulate_facet_dofs(unsigned int* dofs, unsigned int facet) const { switch(facet) { case 0: dofs[0] = 1; dofs[1] = 2; break; case 1: dofs[0] = 0; dofs[1] = 2; break; case 2: dofs[0] = 0; dofs[1] = 1; break; default: throw std::runtime_error("Invalid facet number."); } } /// Tabulate the coordinates of all dofs on a cell void dof_map_Lagrange_1_2D::tabulate_coordinates(double** coordinates, const ufc::cell& c) const { // coordinates double x0 = c.coordinates[0][0]; double y0 = c.coordinates[0][1]; double x1 = c.coordinates[1][0]; double y1 = c.coordinates[1][1]; double x2 = c.coordinates[2][0]; double y2 = c.coordinates[2][1]; // affine map double G00 = x1 - x0; double G01 = x2 - x0; double G10 = y1 - y0; double G11 = y2 - y0; coordinates[0][0] = x0; coordinates[0][1] = y0; coordinates[1][0] = G00+x0; coordinates[1][1] = y0+G10; coordinates[2][0] = x0+G01; coordinates[2][1] = G11+y0; } /// Return the number of sub dof maps (for a mixed element) unsigned int dof_map_Lagrange_1_2D::num_sub_dof_maps() const { return 1; } /// Create a new dof_map for sub dof map i (for a mixed element) ufc::dof_map* dof_map_Lagrange_1_2D::create_sub_dof_map(unsigned int i) const { return new dof_map_Lagrange_1_2D(); } } // namespace ufc-2.3.0/doc/manual/code/stiffness_syfi/dof_map_Lagrange_1_2D.h000066400000000000000000000050571226277264200244270ustar00rootroot00000000000000// // This code complies with UFC version 1.0, and is generated with SyFi version 0.4.0. // // http://www.fenics.org/syfi/ // http://www.fenics.org/ufc/ // #ifndef __dof_map_Lagrange_1_2D_H #define __dof_map_Lagrange_1_2D_H #include #include #include #include #include #include #include #include namespace pycc { /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class dof_map_Lagrange_1_2D: public ufc::dof_map { public: pycc::Dof_Ptv dof; unsigned int num_elements; unsigned int * loc2glob; public: /// Constructor dof_map_Lagrange_1_2D(); /// Destructor virtual ~dof_map_Lagrange_1_2D(); /// Return a string identifying the dof map virtual const char* signature() const; /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(unsigned int d) const; /// Initialize dof map for mesh (return true iff init_cell() is needed) virtual bool init_mesh(const ufc::mesh& m); /// Initialize dof map for given cell virtual void init_cell(const ufc::mesh& m, const ufc::cell& c); /// Finish initialization of dof map for cells virtual void init_cell_finalize(); /// Return the dimension of the global finite element function space virtual unsigned int global_dimension() const; /// Return the dimension of the local finite element function space virtual unsigned int local_dimension() const; /// Return the number of dofs on each cell facet virtual unsigned int num_facet_dofs() const; /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(unsigned int* dofs, const ufc::mesh& m, const ufc::cell& c) const; /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(unsigned int* dofs, unsigned int facet) const; /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double** coordinates, const ufc::cell& c) const; /// Return the number of sub dof maps (for a mixed element) virtual unsigned int num_sub_dof_maps() const; /// Create a new dof_map for sub dof map i (for a mixed element) virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const; }; } // namespace #endif ufc-2.3.0/doc/manual/code/stiffness_syfi/fe_Lagrange_1_2D.cpp000066400000000000000000000073411226277264200237450ustar00rootroot00000000000000// // This code complies with UFC version 1.0, and is generated with SyFi version 0.4.0. // // http://www.fenics.org/syfi/ // http://www.fenics.org/ufc/ // #include #include #include #include #include #include #include #include #include "fe_Lagrange_1_2D.h" namespace pycc { /// Constructor fe_Lagrange_1_2D::fe_Lagrange_1_2D() : ufc::finite_element() { } /// Destructor fe_Lagrange_1_2D::~fe_Lagrange_1_2D() { } /// Return a string identifying the finite element const char* fe_Lagrange_1_2D::signature() const { return "fe_Lagrange_1_2D // generated by SyFi"; } /// Return the cell shape ufc::shape fe_Lagrange_1_2D::cell_shape() const { return ufc::triangle; } /// Return the dimension of the finite element function space unsigned int fe_Lagrange_1_2D::space_dimension() const { return 3; } /// Return the rank of the value space unsigned int fe_Lagrange_1_2D::value_rank() const { return 0; } /// Return the dimension of the value space for axis i unsigned int fe_Lagrange_1_2D::value_dimension(unsigned int i) const { return 1; } /// Evaluate basis function i at given point in cell void fe_Lagrange_1_2D::evaluate_basis(unsigned int i, double* values, const double* coordinates, const ufc::cell& c) const { const double x = coordinates[0]; const double y = coordinates[1]; switch(i) { case 0: values[0] = -x-y+1.0; break; case 1: values[0] = x; break; case 2: values[0] = y; break; } } /// Evaluate order n derivatives of basis function i at given point in cell void fe_Lagrange_1_2D::evaluate_basis_derivatives(unsigned int i, unsigned int n, double* values, const double* coordinates, const ufc::cell& c) const { throw std::runtime_error("gen_evaluate_basis_derivatives not implemented yet."); } /// Evaluate linear functional for dof i on the function f double fe_Lagrange_1_2D::evaluate_dof(unsigned int i, const ufc::function& f, const ufc::cell& c) const { // coordinates double x0 = c.coordinates[0][0]; double y0 = c.coordinates[0][1]; double x1 = c.coordinates[1][0]; double y1 = c.coordinates[1][1]; double x2 = c.coordinates[2][0]; double y2 = c.coordinates[2][1]; // affine map double G00 = x1 - x0; double G01 = x2 - x0; double G10 = y1 - y0; double G11 = y2 - y0; double v[1]; double x[2]; switch(i) { case 0: x[0] = x0; x[1] = y0; break; case 1: x[0] = x0+G00; x[1] = G10+y0; break; case 2: x[0] = G01+x0; x[1] = y0+G11; break; } f.evaluate(v, x, c); return v[i % 1]; } /// Interpolate vertex values from dof values void fe_Lagrange_1_2D::interpolate_vertex_values(double* vertex_values, const double* dof_values, const ufc::cell& c) const { vertex_values[0] = dof_values[0]; vertex_values[1] = dof_values[1]; vertex_values[2] = dof_values[2]; } /// Return the number of sub elements (for a mixed element) unsigned int fe_Lagrange_1_2D::num_sub_elements() const { return 1; } /// Create a new finite element for sub element i (for a mixed element) ufc::finite_element* fe_Lagrange_1_2D::create_sub_element(unsigned int i) const { return new fe_Lagrange_1_2D(); } } // namespace ufc-2.3.0/doc/manual/code/stiffness_syfi/fe_Lagrange_1_2D.h000066400000000000000000000050411226277264200234050ustar00rootroot00000000000000// // This code complies with UFC version 1.0, and is generated with SyFi version 0.4.0. // // http://www.fenics.org/syfi/ // http://www.fenics.org/ufc/ // #ifndef __fe_Lagrange_1_2D_H #define __fe_Lagrange_1_2D_H #include #include #include #include #include #include #include #include namespace pycc { /// This class defines the interface for a finite element. class fe_Lagrange_1_2D: public ufc::finite_element { public: /// Constructor fe_Lagrange_1_2D(); /// Destructor virtual ~fe_Lagrange_1_2D(); /// Return a string identifying the finite element virtual const char* signature() const; /// Return the cell shape virtual ufc::shape cell_shape() const; /// Return the dimension of the finite element function space virtual unsigned int space_dimension() const; /// Return the rank of the value space virtual unsigned int value_rank() const; /// Return the dimension of the value space for axis i virtual unsigned int value_dimension(unsigned int i) const; /// Evaluate basis function i at given point in cell virtual void evaluate_basis(unsigned int i, double* values, const double* coordinates, const ufc::cell& c) const; /// Evaluate order n derivatives of basis function i at given point in cell virtual void evaluate_basis_derivatives(unsigned int i, unsigned int n, double* values, const double* coordinates, const ufc::cell& c) const; /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(unsigned int i, const ufc::function& f, const ufc::cell& c) const; /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const ufc::cell& c) const; /// Return the number of sub elements (for a mixed element) virtual unsigned int num_sub_elements() const; /// Create a new finite element for sub element i (for a mixed element) virtual ufc::finite_element* create_sub_element(unsigned int i) const; }; } // namespace #endif ufc-2.3.0/doc/manual/code/stiffness_syfi/form__stiffness_form__Lagrange_1_2D.cpp000066400000000000000000000126361226277264200277260ustar00rootroot00000000000000// // This code complies with UFC version 1.0, and is generated with SyFi version 0.4.0. // // http://www.fenics.org/syfi/ // http://www.fenics.org/ufc/ // #include #include #include #include #include #include #include #include #include "dof_map_Lagrange_1_2D.h" #include "fe_Lagrange_1_2D.h" #include "form__stiffness_form__Lagrange_1_2D.h" namespace pycc { /// This class defines the interface for the tabulation of the cell /// tensor corresponding to the local contribution to a form from /// the integral over a cell. class cell_itg__stiffness_form__Lagrange_1_2D: public ufc::cell_integral { public: /// Constructor cell_itg__stiffness_form__Lagrange_1_2D(); /// Destructor virtual ~cell_itg__stiffness_form__Lagrange_1_2D(); /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor(double* A, const double * const * w, const ufc::cell& c) const; }; /// Constructor cell_itg__stiffness_form__Lagrange_1_2D::cell_itg__stiffness_form__Lagrange_1_2D() : ufc::cell_integral() { } /// Destructor cell_itg__stiffness_form__Lagrange_1_2D::~cell_itg__stiffness_form__Lagrange_1_2D() { } /// Tabulate the tensor for the contribution from a local cell void cell_itg__stiffness_form__Lagrange_1_2D::tabulate_tensor(double* A, const double * const * w, const ufc::cell& c) const { // coordinates double x0 = c.coordinates[0][0]; double y0 = c.coordinates[0][1]; double x1 = c.coordinates[1][0]; double y1 = c.coordinates[1][1]; double x2 = c.coordinates[2][0]; double y2 = c.coordinates[2][1]; // affine map double G00 = x1 - x0; double G01 = x2 - x0; double G10 = y1 - y0; double G11 = y2 - y0; double detG_tmp = G00*G11-G01*G10; double detG = fabs(detG_tmp); double GinvT00 = G11 / detG_tmp; double GinvT01 = -G10 / detG_tmp; double GinvT10 = -G01 / detG_tmp; double GinvT11 = G00 / detG_tmp; memset(A, 0, sizeof(double)*9); A[3*0 + 0] = detG*((GinvT01*GinvT01)/2.0+(GinvT11*GinvT11)/2.0+GinvT10*GinvT00 +GinvT01*GinvT11+(GinvT00*GinvT00)/2.0+(GinvT10*GinvT10)/2.0); A[3*0 + 1] = detG*(-(GinvT01*GinvT01)/2.0-GinvT10*GinvT00/2.0 -GinvT01*GinvT11/2.0-(GinvT00*GinvT00)/2.0); A[3*0 + 2] = detG*(-(GinvT11*GinvT11)/2.0-GinvT10*GinvT00/2.0 -GinvT01*GinvT11/2.0-(GinvT10*GinvT10)/2.0); A[3*1 + 0] = detG*(-(GinvT01*GinvT01)/2.0-GinvT10*GinvT00/2.0 -GinvT01*GinvT11/2.0-(GinvT00*GinvT00)/2.0); A[3*1 + 1] = detG*((GinvT01*GinvT01)/2.0+(GinvT00*GinvT00)/2.0); A[3*1 + 2] = detG*(GinvT10*GinvT00/2.0+GinvT01*GinvT11/2.0); A[3*2 + 0] = detG*(-(GinvT11*GinvT11)/2.0-GinvT10*GinvT00/2.0 -GinvT01*GinvT11/2.0-(GinvT10*GinvT10)/2.0); A[3*2 + 1] = detG*(GinvT10*GinvT00/2.0+GinvT01*GinvT11/2.0); A[3*2 + 2] = detG*((GinvT11*GinvT11)/2.0+(GinvT10*GinvT10)/2.0); } /// Constructor form__stiffness_form__Lagrange_1_2D::form__stiffness_form__Lagrange_1_2D() : ufc::form() { } /// Destructor form__stiffness_form__Lagrange_1_2D::~form__stiffness_form__Lagrange_1_2D() { } /// Return a string identifying the form const char* form__stiffness_form__Lagrange_1_2D::signature() const { return "form__stiffness_form__Lagrange_1_2D // generated by SyFi"; } /// Return the rank of the global tensor (r) unsigned int form__stiffness_form__Lagrange_1_2D::rank() const { return 2; } /// Return the number of coefficients (n) unsigned int form__stiffness_form__Lagrange_1_2D::num_coefficients() const { return 0; } /// Return the number of cell integrals unsigned int form__stiffness_form__Lagrange_1_2D::num_cell_integrals() const { return 1; } /// Return the number of exterior facet integrals unsigned int form__stiffness_form__Lagrange_1_2D::num_exterior_facet_integrals() const { return 0; } /// Return the number of interior facet integrals unsigned int form__stiffness_form__Lagrange_1_2D::num_interior_facet_integrals() const { return 0; } /// Create a new finite element for argument function i ufc::finite_element* form__stiffness_form__Lagrange_1_2D:: create_finite_element(unsigned int i) const { switch(i) { case 0: return new fe_Lagrange_1_2D(); case 1: return new fe_Lagrange_1_2D(); } throw std::runtime_error("Invalid index in create_finite_element()"); } /// Create a new dof map for argument function i ufc::dof_map* form__stiffness_form__Lagrange_1_2D::create_dof_map(unsigned int i) const { switch(i) { case 0: return new dof_map_Lagrange_1_2D(); case 1: return new dof_map_Lagrange_1_2D(); } throw std::runtime_error("Invalid index in create_dof_map()"); } /// Create a new cell integral on sub domain i ufc::cell_integral* form__stiffness_form__Lagrange_1_2D:: create_cell_integral(unsigned int i) const { return new cell_itg__stiffness_form__Lagrange_1_2D(); } /// Create a new exterior facet integral on sub domain i ufc::exterior_facet_integral* form__stiffness_form__Lagrange_1_2D:: create_exterior_facet_integral(unsigned int i) const { return 0; } /// Create a new interior facet integral on sub domain i ufc::interior_facet_integral* form__stiffness_form__Lagrange_1_2D:: create_interior_facet_integral(unsigned int i) const { return 0; } } // namespace ufc-2.3.0/doc/manual/code/stiffness_syfi/form__stiffness_form__Lagrange_1_2D.h000066400000000000000000000051101226277264200273600ustar00rootroot00000000000000// // This code complies with UFC version 1.0, and is generated with SyFi version 0.4.0. // // http://www.fenics.org/syfi/ // http://www.fenics.org/ufc/ // #ifndef __form__stiffness_form__Lagrange_1_2D_H #define __form__stiffness_form__Lagrange_1_2D_H #include #include #include #include #include #include #include #include #include "dof_map_Lagrange_1_2D.h" #include "fe_Lagrange_1_2D.h" namespace pycc { /// This class defines the interface for the assembly of the global /// tensor corresponding to a form with r + n arguments, that is, a /// mapping /// /// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R /// /// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r /// global tensor A is defined by /// /// A = a(V1, V2, ..., Vr, w1, w2, ..., wn), /// /// where each argument Vj represents the application to the /// sequence of basis functions of Vj and w1, w2, ..., wn are given /// fixed functions (coefficients). class form__stiffness_form__Lagrange_1_2D: public ufc::form { public: /// Constructor form__stiffness_form__Lagrange_1_2D(); /// Destructor virtual ~form__stiffness_form__Lagrange_1_2D(); /// Return a string identifying the form virtual const char* signature() const; /// Return the rank of the global tensor (r) virtual unsigned int rank() const; /// Return the number of coefficients (n) virtual unsigned int num_coefficients() const; /// Return the number of cell integrals virtual unsigned int num_cell_integrals() const; /// Return the number of exterior facet integrals virtual unsigned int num_exterior_facet_integrals() const; /// Return the number of interior facet integrals virtual unsigned int num_interior_facet_integrals() const; /// Create a new finite element for argument function i virtual ufc::finite_element* create_finite_element(unsigned int i) const; /// Create a new dof map for argument function i virtual ufc::dof_map* create_dof_map(unsigned int i) const; /// Create a new cell integral on sub domain i virtual ufc::cell_integral* create_cell_integral(unsigned int i) const; /// Create a new exterior facet integral on sub domain i virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const; /// Create a new interior facet integral on sub domain i virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const; }; } // namespace #endif ufc-2.3.0/doc/manual/eps/000077500000000000000000000000001226277264200151145ustar00rootroot00000000000000ufc-2.3.0/doc/manual/eps/hexahedron.eps000066400000000000000000000073461226277264200177640ustar00rootroot00000000000000%!PS-Adobe-3.0 EPSF-3.0 %%Creator: inkscape 0.44 %%Pages: 1 %%Orientation: Portrait %%BoundingBox: 32 56 543 470 %%HiResBoundingBox: 32.571875 56 542.36875 469.99688 %%EndComments %%Page: 1 1 0 842 translate 0.8 -0.8 scale gsave [1 0 0 1 0 0] concat 0 0 0 setrgbcolor [] 0 setdash 3 setlinewidth 0 setlinejoin 0 setlinecap newpath 140 852.36218 moveto 492.81509 958.50976 lineto stroke gsave [-1.7236793 -0.51858435 0.51858435 -1.7236793 492.81509 958.50976] concat gsave 0 0 0 setrgbcolor newpath 8.7185878 4.0337352 moveto -2.2072895 0.016013256 lineto 8.7185884 -4.0017078 lineto 6.97309 -1.6296469 6.9831476 1.6157441 8.7185878 4.0337352 curveto closepath eofill grestore grestore gsave [1 0 0 -1 40 872.36218] concat gsave /newlatin1font {findfont dup length dict copy dup /Encoding ISOLatin1Encoding put definefont} def /BitstreamVeraSans-Roman-ISOLatin1 /BitstreamVeraSans-Roman newlatin1font 24 scalefont setfont 0 0 0 setrgbcolor newpath 0 0 moveto (v0) show grestore grestore gsave [1 0 0 -1 380 982.36218] concat gsave /BitstreamVeraSans-Roman-ISOLatin1 findfont 24 scalefont setfont 0 0 0 setrgbcolor newpath 0 0 moveto (v1) show grestore grestore gsave [1 0 0 -1 650 842.36218] concat gsave /BitstreamVeraSans-Roman-ISOLatin1 findfont 24 scalefont setfont 0 0 0 setrgbcolor newpath 0 0 moveto (v2) show grestore grestore gsave [1 0 0 -1 40 522.36218] concat gsave /BitstreamVeraSans-Roman-ISOLatin1 findfont 24 scalefont setfont 0 0 0 setrgbcolor newpath 0 0 moveto (v4) show grestore grestore gsave 0.38431373 0.52549022 0.92941177 setrgbcolor newpath 140 852.36218 moveto 440 942.36218 lineto 440 552.36218 lineto 140 522.36218 lineto 140 852.36218 lineto closepath eofill grestore gsave 0.27450982 0.41960785 0.83529413 setrgbcolor newpath 440 942.36218 moveto 640 832.36218 lineto 640 522.36218 lineto 440 552.36218 lineto 440 942.36218 lineto closepath eofill grestore gsave 0.21568628 0.39607844 0.9137255 setrgbcolor newpath 140 522.36218 moveto 440 552.36218 lineto 640 522.36218 lineto 370 502.36218 lineto 140 522.36218 lineto closepath eofill grestore 0.29411766 0.29411766 0.58823532 setrgbcolor [18 6] 0 setdash 3 setlinewidth 0 setlinejoin 0 setlinecap newpath 370 502.36218 moveto 370 772.36218 lineto stroke 0.29411766 0.29411766 0.58823532 setrgbcolor [18 6] 0 setdash 3 setlinewidth 0 setlinejoin 0 setlinecap newpath 140 852.36218 moveto 370 772.36218 lineto 640 832.36218 lineto stroke 0 0 0 setrgbcolor [] 0 setdash 3 setlinewidth 0 setlinejoin 0 setlinecap newpath 140 852.36218 moveto 140 482.36218 lineto stroke gsave [-1.1021457e-16 1.8 -1.8 -1.1021457e-16 140 482.36218] concat gsave 0 0 0 setrgbcolor newpath 8.7185878 4.0337352 moveto -2.2072895 0.016013256 lineto 8.7185884 -4.0017078 lineto 6.97309 -1.6296469 6.9831476 1.6157441 8.7185878 4.0337352 curveto closepath eofill grestore grestore gsave [1 0 0 -1 650 512.36218] concat gsave /BitstreamVeraSans-Roman-ISOLatin1 findfont 24 scalefont setfont 0 0 0 setrgbcolor newpath 0 0 moveto (v6) show grestore grestore gsave [1 0 0 -1 330 482.36218] concat gsave /BitstreamVeraSans-Roman-ISOLatin1 findfont 24 scalefont setfont 0 0 0 setrgbcolor newpath 0 0 moveto (v7) show grestore grestore 0 0 0 setrgbcolor [] 0 setdash 3 setlinewidth 0 setlinejoin 0 setlinecap newpath 140 852.36218 moveto 440 942.36218 lineto 440 552.36218 lineto stroke 0 0 0 setrgbcolor [] 0 setdash 3 setlinewidth 0 setlinejoin 0 setlinecap newpath 140 522.36218 moveto 440 552.36218 lineto 640 522.36218 lineto stroke 0 0 0 setrgbcolor [] 0 setdash 3 setlinewidth 0 setlinejoin 0 setlinecap newpath 440 942.36218 moveto 640 832.36218 lineto 640 522.36218 lineto stroke 0 0 0 setrgbcolor [] 0 setdash 2.8 setlinewidth 0 setlinejoin 0 setlinecap newpath 140 522.36218 moveto 370 502.36218 lineto 640 522.36218 lineto stroke grestore showpage %%EOF ufc-2.3.0/doc/manual/eps/insertion.eps000066400000000000000000000305561226277264200176500ustar00rootroot00000000000000%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 60 258 582 592 %%HiResBoundingBox: 60.809375 258.244922 581.239844 591.487500 %................................... %%Creator: ESP Ghostscript 81504 (epswrite) %%CreationDate: 2007/09/08 00:52:13 %%DocumentData: Clean7Bit %%LanguageLevel: 2 %%EndComments %%BeginProlog % This copyright applies to everything between here and the %%EndProlog: % Copyright (C) 2004 artofcode LLC, Benicia, CA. All rights reserved. %%BeginResource: procset GS_epswrite_2_0_1001 /GS_epswrite_2_0_1001 80 dict dup begin /PageSize 2 array def/setpagesize{ PageSize aload pop 3 index eq exch 4 index eq and{ pop pop pop}{ PageSize dup 1 5 -1 roll put 0 4 -1 roll put dup null eq {false} {dup where} ifelse{ exch get exec} { pop/setpagedevice where { pop 1 dict dup /PageSize PageSize put setpagedevice} { /setpage where{ pop PageSize aload pop pageparams 3 {exch pop} repeat setpage}if}ifelse}ifelse}ifelse} bind def /!{bind def}bind def/#{load def}!/N/counttomark # /rG{3{3 -1 roll 255 div}repeat setrgbcolor}!/G{255 div setgray}!/K{0 G}! /r6{dup 3 -1 roll rG}!/r5{dup 3 1 roll rG}!/r3{dup rG}! /w/setlinewidth #/J/setlinecap # /j/setlinejoin #/M/setmiterlimit #/d/setdash #/i/setflat # /m/moveto #/l/lineto #/c/rcurveto # /p{N 2 idiv{N -2 roll rlineto}repeat}! /P{N 0 gt{N -2 roll moveto p}if}! /h{p closepath}!/H{P closepath}! /lx{0 rlineto}!/ly{0 exch rlineto}!/v{0 0 6 2 roll c}!/y{2 copy c}! /re{4 -2 roll m exch dup lx exch ly neg lx h}! /^{3 index neg 3 index neg}! /f{P fill}!/f*{P eofill}!/s{H stroke}!/S{P stroke}! /q/gsave #/Q/grestore #/rf{re fill}! /Y{P clip newpath}!/Y*{P eoclip newpath}!/rY{re Y}! /|={pop exch 4 1 roll 1 array astore cvx 3 array astore cvx exch 1 index def exec}! /|{exch string readstring |=}! /+{dup type/nametype eq{2 index 7 add -3 bitshift 2 index mul}if}! /@/currentfile #/${+ @ |}! /B{{2 copy string{readstring pop}aload pop 4 array astore cvx 3 1 roll}repeat pop pop true}! /Ix{[1 0 0 1 11 -2 roll exch neg exch neg]exch}! /,{true exch Ix imagemask}!/If{false exch Ix imagemask}!/I{exch Ix image}! /Ic{exch Ix false 3 colorimage}! /F{/Columns counttomark 3 add -2 roll/Rows exch/K -1/BlackIs1 true>> /CCITTFaxDecode filter}!/FX{<} \newcommand{\@fenicspackagett}{} \newcommand{\fenicspackage}[2]{\renewcommand{\@fenicspackage}{#1}\renewcommand{\@fenicspackagett}{#2}} \newcommand{\package}{\@fenicspackage} \newcommand{\packagett}{\@fenicspackagett} %--- Commands --- \renewcommand{\maketitle}{ \lhead{\textsf{\textbf{\@fenicstitle}}} \rhead{\textsf{\@fenicsauthor}} \pagestyle{fancy} \renewcommand{\footrulewidth}{2pt} \renewcommand{\headrulewidth}{2pt} \thispagestyle{empty} \Large\textsf{\textbf{\@fenicstitle}} \\ \vspace{-0.5cm} \hrule height 2pt \hfill\large\textsf{\today} \vspace{3cm} \@fenicsimage \vfill\large\textsf{\textbf{\@fenicsauthor}} \\ \hrule height 2pt \hfill\large\texttt{www.fenics.org} \newpage \null\vfill \normalsize Visit \texttt{http://www.fenics.org/} for the latest version of this manual. \\ Send comments and suggestions to \texttt{\@fenicspackagett{}-dev@fenics.org}. \pagestyle{empty} \cleardoublepage \tableofcontents \cleardoublepage \pagestyle{fancy}} \newcommand{\fenics}{\textbf{\textsf{\normalsize{FE}\Large{ni}\normalsize{CS}}}} \newcommand{\dolfin}{\textbf{\textsf{DOLFIN}}} \newcommand{\pydolfin}{\textbf{\textsf{PyDOLFIN}}} \newcommand{\ffc}{\textbf{\textsf{FFC}}} \newcommand{\fiat}{\textbf{\textsf{FIAT}}} \newcommand{\fixme}[1]{\ \\ \begin{tabular}{||p{\textwidth}||}\hline\rm\textbf{FIXME:}\rm #1 \\ \hline\end{tabular} \\} \newcommand{\devnote}[1]{$\blacktriangleright$ \emph{Developer's note:} #1} %--- Environments --- \DefineVerbatimEnvironment{code}{Verbatim}{frame=single,rulecolor=\color{blue}} \DefineVerbatimEnvironment{macrocode}{Verbatim}{commandchars=\\\{\},frame=single,rulecolor=\color{blue}} %--- Macros --- \newcommand{\dx}{\, \mathrm{d}x} \newcommand{\dX}{\, \mathrm{d}X} \newcommand{\ds}{\, \mathrm{d}s} \newcommand{\dS}{\, \mathrm{d}S} \newcommand{\R}{\mathbb{R}} ufc-2.3.0/doc/manual/svg/000077500000000000000000000000001226277264200151245ustar00rootroot00000000000000ufc-2.3.0/doc/manual/svg/hexahedron.svg000066400000000000000000000240111226277264200177700ustar00rootroot00000000000000 image/svg+xml v0 v1 v2 v4 v6 v7 ufc-2.3.0/doc/manual/svg/insertion.svg000066400000000000000000000476351226277264200176760ustar00rootroot00000000000000 image/svg+xml i0 i1 i2 j0 j1 j2 1 2 3 1 2 3 A21 ufc-2.3.0/doc/manual/svg/interval.svg000066400000000000000000000135301226277264200174730ustar00rootroot00000000000000 image/svg+xml 0 1 ufc-2.3.0/doc/manual/svg/numbering_example_quadrilaterals.svg000066400000000000000000000403751226277264200244540ustar00rootroot00000000000000 image/svg+xml 5 v0 0 1 2 3 4 v1 v2 v3 v0 v3 v2 v1 ufc-2.3.0/doc/manual/svg/numbering_example_triangles.svg000066400000000000000000000327171226277264200234300ustar00rootroot00000000000000 image/svg+xml 0 1 3 2 v0 v1 v2 v0 v1 v2 ufc-2.3.0/doc/manual/svg/ordering_example_tetrahedron.svg000066400000000000000000000201271226277264200235720ustar00rootroot00000000000000 image/svg+xml v0 v1 v2 v3 e0 ufc-2.3.0/doc/manual/svg/ordering_example_triangle.svg000066400000000000000000000135711226277264200230650ustar00rootroot00000000000000 image/svg+xml v0 v1 v2 e0 ufc-2.3.0/doc/manual/svg/orientation_example_triangles.svg000066400000000000000000000364551226277264200240000ustar00rootroot00000000000000 image/svg+xml v0 v1 v2 v0 v1 v2 ufc-2.3.0/doc/manual/svg/quadrilateral.svg000066400000000000000000000153771226277264200205140ustar00rootroot00000000000000 image/svg+xml v0 v1 v2 v3 ufc-2.3.0/doc/manual/svg/tetrahedron.svg000066400000000000000000000211671226277264200201730ustar00rootroot00000000000000 image/svg+xml v0 v1 v2 v3 ufc-2.3.0/doc/manual/svg/triangle.svg000066400000000000000000000137461226277264200174650ustar00rootroot00000000000000 image/svg+xml v0 v1 v2 ufc-2.3.0/doc/manual/ufc-user-manual.tex000066400000000000000000000014151226277264200200540ustar00rootroot00000000000000\documentclass{fenicsmanual} \begin{document} \fenicstitle{UFC Specification and User Manual 1.1} \fenicsauthor{Martin Sandve Aln\ae{}s, Anders Logg, Kent-Andre Mardal, Ola Skavhaug, and Hans Petter Langtangen} \fenicspackage{\textbf{\textsf{UFC}}}{ufc} \maketitle \rhead{} \newcommand{\ufc}{UFC} \input{chapters/introduction.tex} \input{chapters/assembly.tex} \input{chapters/interface.tex} \input{chapters/referencecells.tex} \input{chapters/numbering.tex} \newpage \bibliographystyle{siam} \bibliography{bibliography} \appendix \input{chapters/interface_cpp.tex} \input{chapters/assembly_cpp.tex} \input{chapters/examples.tex} \input{chapters/pythonutils.tex} \input{chapters/installation.tex} \input{chapters/versions.tex} \input{chapters/license.tex} \end{document} ufc-2.3.0/doc/sphinx/000077500000000000000000000000001226277264200143615ustar00rootroot00000000000000ufc-2.3.0/doc/sphinx/README000066400000000000000000000002631226277264200152420ustar00rootroot00000000000000This file has been moved here from the fenics-web (old fenics-doc) repository. It needs to be checked and possible expanded, then integrated with the online documentation system. ufc-2.3.0/doc/sphinx/index.rst000066400000000000000000000106621226277264200162270ustar00rootroot00000000000000.. UFC documentation .. _ufc_introduction: ################# UFC documentation ################# ============ Introduction ============ Large parts of a finite element program are similar from problem to problem and can therefore be coded as a general, reusable library. Mesh data structures, linear algebra and finite element assembly are examples of operations that are naturally coded in a problem-independent way and made available in reusable libraries~\cite{www:fenics,www:petsc,www:sundance,www:deal.II,www:trilinos,www:diffpack}. However, some parts of a finite element program are difficult to code in a problem-independent way. In particular, this includes the evaluation of the \emph{element tensor} (the `element stiffness matrix'), that is, the evaluation of the local contribution from a finite element to a global sparse tensor (the ``stiffness matrix'') representing a discretized differential operator. These parts must thus be implemented by the application programmer for each specific combination of differential equation and discretization (finite element spaces). \index{form compilers} \index{FFC} \index{SyFi} However, domain-specific compilers such as FFC~\cite{www:ffc,logg:article:07,logg:article:09,logg:article:10,logg:article:11} and SyFi~\cite{www:syfi} make it possible to automatically generate the code for the evaluation of the element tensor. These \emph{form compilers} accept as input a high-level description of a finite element variational form and generate low-level code code for efficient evaluation of the element tensor and associated quantities. It thus becomes important to specify the \emph{interface} between form compilers and finite element assemblers such that the code generated by FFC, SyFi and other form compilers can be used to assemble finite element matrices and vectors (and in general tensors). Unified Form-assembly Code ========================== UFC (Unified Form-assembly Code) is a unified framework for finite element assembly. More precisely, it defines a fixed interface for communicating low level routines (functions) for evaluating and assembling finite element variational forms. The UFC interface consists of a single header file \texttt{ufc.h} that specifies a C++ interface that must be implemented by code that complies with the UFC specification. Both FFC (since version 0.4.0) and SyFi (since version 0.3.4) generate code that complies with the UFC specification. Thus, code generated by FFC and SyFi may be used interchangeably by any UFC-based finite element assembler, such as DOLFIN~\cite{www:dolfin}. Aim and scope ============= The UFC interface has been designed to make a minimal amount of assumptions on the form compilers generating the UFC code and the assemblers built on top of the UFC specification. Thus, the UFC specification provides a minimal amount of abstractions and data structures. Programmers wishing to implement the UFC specification will typically want to create system-specific (but simple) wrappers for the generated code. Few assumptions have also been made on the underlying finite element methodology. The current specification is limited to affinely mapped cells, but does not restrict the mapping of finite element function spaces. Thus, UFC code may be generated for elements where basis functions are transformed from the reference cell by the affine mapping, as well as for elements where the basis functions must be transformed by the Piola mapping. UFC code has been successfully generated and used in finite element codes for standard continuous Galerkin methods (Lagrange finite elements of arbitrary order), discontinuous Galerkin methods (including integrals of jumps and averages over interior facets) and mixed methods (including Brezzi--Douglas--Marini and Raviart--Thomas elements). Outline ======= In the next section, we give an overview of finite element assembly and explain how the code generated by form compilers may be used as the basic building blocks in the assembly algorithm. We then present the UFC interface in detail in Section~\ref{sec:interface}. In Section~\ref{sec:referencecells} and Section~\ref{sec:numbering}, we define the reference cells and numbering conventions that must be followed by UFC-based form compilers and assemblers. ======================= Finite element assembly ======================= In this section, we present a general algorithm for assembly of finite element variational forms and define the concepts that the UFC interface is based on. ufc-2.3.0/release.conf000066400000000000000000000012371226277264200145750ustar00rootroot00000000000000# Configuration file for fenics-release PACKAGE="ufc" BRANCH="master" FILES="ChangeLog \ README.rst \ CMakeLists.txt \ src/ufc/ufc.h \ src/utils/python/ufc_benchmark/ufc_benchmark.cpp \ src/utils/python/ufc_benchmark/ufc_benchmark.h \ src/utils/python/ufc_benchmark/ufc_data.h \ src/utils/python/ufc_benchmark/ufc_reference_cell.h \ src/utils/python/ufc_utils/__init__.py \ src/utils/python/ufc_utils/dofmap.py \ src/utils/python/ufc_utils/finite_element.py \ src/utils/python/ufc_utils/form.py \ src/utils/python/ufc_utils/function.py \ src/utils/python/ufc_utils/integrals.py" ufc-2.3.0/src/000077500000000000000000000000001226277264200130725ustar00rootroot00000000000000ufc-2.3.0/src/ufc/000077500000000000000000000000001226277264200136475ustar00rootroot00000000000000ufc-2.3.0/src/ufc/__init__.py000066400000000000000000000006631226277264200157650ustar00rootroot00000000000000__author__ = "Johan Hake (hake.dev@gmail.com)" __copyright__ = "Copyright (C) 2010 Johan Hake" __date__ = "2010-08-19 -- 2013-02-01" __license__ = "Released to the public domain" # Import Python versions of the abstract classes in the UFC interface from ufc import cell, function, form, finite_element, dofmap, cell_integral,\ exterior_facet_integral, interior_facet_integral, point_integral,\ __version__, __swigversion__ ufc-2.3.0/src/ufc/ufc.h000066400000000000000000000361071226277264200146040ustar00rootroot00000000000000// This is UFC (Unified Form-assembly Code) v. 2.3.0. // This code is released into the public domain. // // The FEniCS Project (http://www.fenicsproject.org/) 2006-2014. #ifndef __UFC_H #define __UFC_H #define UFC_VERSION_MAJOR 2 #define UFC_VERSION_MINOR 3 #define UFC_VERSION_MAINTENANCE 0 #include #include #include #include const char UFC_VERSION[] = "2.3.0"; namespace ufc { /// Valid cell shapes enum shape {interval, triangle, quadrilateral, tetrahedron, hexahedron}; /// This class defines the interface for cell topology data. class cell_topology { public: /// Destructor virtual ~cell_topology() {} /// Return array of global entity indices for topological dimension d //virtual const std::size_t* entity_indices(std::size_t d) const; }; /// This class defines the interface for cell geometry data. class cell_geometry { public: /// Destructor virtual ~cell_geometry() {} /// Get vertex coordinates //virtual void get_vertex_coordinates(const double* x[]) const; //virtual std::vector >& void vertex_coordinates() const; }; /// This class defines the data structure for a cell in a mesh. class cell { public: /// Constructor cell(): cell_shape(interval), topological_dimension(0), geometric_dimension(0), index(0), local_facet(-1), mesh_identifier(-1) {} /// Destructor virtual ~cell() {} /// Shape of the cell shape cell_shape; /// Topological dimension of the mesh std::size_t topological_dimension; /// Geometric dimension of the mesh std::size_t geometric_dimension; /// Array of global indices for the mesh entities of the cell std::vector > entity_indices; /// Cell index (short-cut for entity_indices[topological_dimension][0]) std::size_t index; /// Local facet index int local_facet; /// Cell orientation int orientation; /// Unique mesh identifier int mesh_identifier; }; /// This class defines the interface for a general tensor-valued function. class function { public: /// Destructor virtual ~function() {} /// Evaluate function at given point in cell virtual void evaluate(double* values, const double* coordinates, const cell& c) const = 0; }; /// This class defines the interface for a finite element. class finite_element { public: /// Destructor virtual ~finite_element() {} /// Return a string identifying the finite element virtual const char* signature() const = 0; /// Return the cell shape virtual shape cell_shape() const = 0; /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const = 0; /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const = 0; /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const = 0; /// Return the rank of the value space virtual std::size_t value_rank() const = 0; /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const = 0; /// Evaluate basis function i at given point x in cell virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const = 0; /// Evaluate all basis functions at given point x in cell virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const = 0; /// Evaluate order n derivatives of basis function i at given point x in cell virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const = 0; /// Evaluate order n derivatives of all basis functions at given point x in cell virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const = 0; // FIXME: cell argument only included here so we can pass it to the eval function... /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const function& f, const double* vertex_coordinates, int cell_orientation, const cell& c) const = 0; /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const function& f, const double* vertex_coordinates, int cell_orientation, const cell& c) const = 0; /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const cell& c) const = 0; /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const cell& c) const = 0; /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const cell& c) const = 0; /// Return the number of sub elements (for a mixed element) virtual std::size_t num_sub_elements() const = 0; /// Create a new finite element for sub element i (for a mixed element) virtual finite_element* create_sub_element(std::size_t i) const = 0; /// Create a new class instance virtual finite_element* create() const = 0; }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class dofmap { public: /// Destructor virtual ~dofmap() {} /// Return a string identifying the dofmap virtual const char* signature() const = 0; /// Return true iff mesh entities of topological dimension d are /// needed virtual bool needs_mesh_entities(std::size_t d) const = 0; /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const = 0; /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const = 0; /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_mesh_entities) const = 0; /// Return the dimension of the local finite element function space /// for a cell virtual std::size_t local_dimension() const = 0; /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const = 0; /// Return the number of dofs associated with each cell entity of /// dimension d virtual std::size_t num_entity_dofs(std::size_t d) const = 0; /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const cell& c) const = 0; /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(std::size_t* dofs, std::size_t facet) const = 0; /// Tabulate the local-to-local mapping of dofs on entity (d, i) virtual void tabulate_entity_dofs(std::size_t* dofs, std::size_t d, std::size_t i) const = 0; /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double** dof_coordinates, const double* vertex_coordinates) const = 0; /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const = 0; /// Create a new dofmap for sub dofmap i (for a mixed element) virtual dofmap* create_sub_dofmap(std::size_t i) const = 0; /// Create a new class instance virtual dofmap* create() const = 0; }; /// This class defines the interface for the tabulation of the cell /// tensor corresponding to the local contribution to a form from /// the integral over a cell. class cell_integral { public: /// Destructor virtual ~cell_integral() {} /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor(double* A, const double * const * w, const double* vertex_coordinates, int cell_orientation) const = 0; // FIXME: New experimental version /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor_new(double* A, const double * const * w, const cell_geometry& c) const {} }; /// This class defines the interface for the tabulation of the /// exterior facet tensor corresponding to the local contribution to /// a form from the integral over an exterior facet. class exterior_facet_integral { public: /// Destructor virtual ~exterior_facet_integral() {} /// Tabulate the tensor for the contribution from a local exterior facet virtual void tabulate_tensor(double* A, const double * const * w, const double* vertex_coordinates, std::size_t facet) const = 0; }; /// This class defines the interface for the tabulation of the /// interior facet tensor corresponding to the local contribution to /// a form from the integral over an interior facet. class interior_facet_integral { public: /// Destructor virtual ~interior_facet_integral() {} /// Tabulate the tensor for the contribution from a local interior facet virtual void tabulate_tensor(double* A, const double * const * w, const double* vertex_coordinates_0, const double* vertex_coordinates_1, std::size_t facet_0, std::size_t facet_1) const = 0; }; /// This class defines the interface for the tabulation of /// an expression evaluated at exactly one point. class point_integral { public: /// Constructor point_integral() {} /// Destructor virtual ~point_integral() {} /// Tabulate the tensor for the contribution from the local vertex virtual void tabulate_tensor(double* A, const double * const * w, const double* vertex_coordinates, std::size_t vertex) const = 0; }; /// This class defines the interface for the assembly of the global /// tensor corresponding to a form with r + n arguments, that is, a /// mapping /// /// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R /// /// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r /// global tensor A is defined by /// /// A = a(V1, V2, ..., Vr, w1, w2, ..., wn), /// /// where each argument Vj represents the application to the /// sequence of basis functions of Vj and w1, w2, ..., wn are given /// fixed functions (coefficients). class form { public: /// Destructor virtual ~form() {} /// Return a string identifying the form virtual const char* signature() const = 0; /// Return the rank of the global tensor (r) virtual std::size_t rank() const = 0; /// Return the number of coefficients (n) virtual std::size_t num_coefficients() const = 0; /// Return the number of cell domains virtual std::size_t num_cell_domains() const = 0; /// Return the number of exterior facet domains virtual std::size_t num_exterior_facet_domains() const = 0; /// Return the number of interior facet domains virtual std::size_t num_interior_facet_domains() const = 0; /// Return the number of point domains virtual std::size_t num_point_domains() const = 0; /// Return whether form has any cell integrals virtual bool has_cell_integrals() const = 0; /// Return whether form has any exterior facet integrals virtual bool has_exterior_facet_integrals() const = 0; /// Return whether form has any interior facet integrals virtual bool has_interior_facet_integrals() const = 0; /// Return whether form has any point integrals virtual bool has_point_integrals() const = 0; /// Create a new finite element for argument function i virtual finite_element* create_finite_element(std::size_t i) const = 0; /// Create a new dofmap for argument function i virtual dofmap* create_dofmap(std::size_t i) const = 0; /// Create a new cell integral on sub domain i virtual cell_integral* create_cell_integral(std::size_t i) const = 0; /// Create a new exterior facet integral on sub domain i virtual exterior_facet_integral* create_exterior_facet_integral(std::size_t i) const = 0; /// Create a new interior facet integral on sub domain i virtual interior_facet_integral* create_interior_facet_integral(std::size_t i) const = 0; /// Create a new point integral on sub domain i virtual point_integral* create_point_integral(std::size_t i) const = 0; /// Create a new cell integral on everywhere else virtual cell_integral* create_default_cell_integral() const = 0; /// Create a new exterior facet integral on everywhere else virtual exterior_facet_integral* create_default_exterior_facet_integral() const = 0; /// Create a new interior facet integral on everywhere else virtual interior_facet_integral* create_default_interior_facet_integral() const = 0; /// Create a new point integral on everywhere else virtual point_integral* create_default_point_integral() const = 0; }; } #endif ufc-2.3.0/src/ufc/ufc.i000066400000000000000000000054741226277264200146100ustar00rootroot00000000000000%module ufc %{ #include "ufc.h" // If using std::tr1::shared_ptr comment out this line #include // Un comment this line to use std::tr1, only works with swig version >= 1.3.37 //#include %} // Un comment these lines to use std::tr1, only works with swig version >= 1.3.37 //#define SWIG_SHARED_PTR_NAMESPACE std //#define SWIG_SHARED_PTR_SUBNAMESPACE tr1 %include // Ignore interface to ufc::cell that will not be available for the user %ignore ufc::cell::entity_indices; // Declare which classes should be stored using shared_ptr %shared_ptr(ufc::cell_integral) %shared_ptr(ufc::dofmap) %shared_ptr(ufc::finite_element) %shared_ptr(ufc::function) %shared_ptr(ufc::form) %shared_ptr(ufc::exterior_facet_integral) %shared_ptr(ufc::interior_facet_integral) %shared_ptr(ufc::point_integral) %include //----------------------------------------------------------------------------- // Home brewed versions of the SWIG provided SWIG_AsVal(Type). //----------------------------------------------------------------------------- %fragment("Py_convert_uint", "header") { // A check for int and converter to uint SWIGINTERNINLINE bool Py_convert_uint(PyObject* in, std::size_t& value) { if (!(PyInt_Check(in) && PyInt_AS_LONG(in)>=0)) return false; value = static_cast(PyInt_AS_LONG(in)); return true; } } //----------------------------------------------------------------------------- // Out typemap (std::size_t) //----------------------------------------------------------------------------- %typemap(out) std::size_t { // Typemap std::size_t $result = PyInt_FromLong(static_cast< long >($1)); } //----------------------------------------------------------------------------- // Typecheck and in typemap (std::size_t) //----------------------------------------------------------------------------- %typecheck(SWIG_TYPECHECK_INTEGER) std::size_t { $1 = PyInt_Check($input) ? 1 : 0; } %typemap(in, fragment="Py_convert_uint") std::size_t { if (!Py_convert_uint($input, $1)) SWIG_exception(SWIG_TypeError, "expected positive 'int' for argument $argnum"); } //----------------------------------------------------------------------------- // Include the main header file //----------------------------------------------------------------------------- %include "ufc.h" // Include code to generate a __swigversion__ attribute to the cpp module // Add prefix to avoid naming problems with other modules %inline %{ int ufc_swigversion() { return SWIGVERSION; } %} %pythoncode %{ __version__ = UFC_VERSION del UFC_VERSION, UFC_VERSION_MAJOR, UFC_VERSION_MINOR """Code for adding swig version to ufc extension module.""" tmp = hex(ufc_swigversion()) __swigversion__ = "%d.%d.%d"%(tuple(map(int, [tmp[-5], tmp[-3], tmp[-2:]]))) del tmp, ufc_swigversion %} ufc-2.3.0/src/ufc/ufc_geometry.h000066400000000000000000000742141226277264200165200ustar00rootroot00000000000000// This file provides utility functions for computing geometric quantities. // This code is released into the public domain. // // The FEniCS Project (http://www.fenicsproject.org/) 2013. #ifndef __UFC_GEOMETRY_H #define __UFC_GEOMETRY_H #include /// A note regarding data structures. All matrices are represented as /// row-major flattened raw C++ arrays. Benchmarks indicate that when /// optimization (-O1 and up) is used, the following conditions hold: /// /// 1. std::vector is just as fast as raw C++ arrays for indexing. /// /// 2. Flattened arrays are twice as fast as nested arrays, both for /// std:vector and raw C++ arrays. /// /// 3. Defining an array by 'std::vector x(n)', where n is a /// literal, leads to dynamic allocation and results in significant /// slowdowns compared to the definition 'double x[n]'. /// /// The conclusion is that we should use flattened raw C++ arrays in /// the interfaces for these utility functions, since some of the /// arrays passed to these functions (in particular Jacobians) are /// created inside the generated functions (tabulate_tensor). Note /// that an std::vector x may also be passed as raw pointer by &x[0]. // TODO: Should signatures of compute___d match for each foo? // On one hand the snippets use different quantities, on the other // some consistency is nice to simplify the code generation. // Currently only the arguments that are actually used are included. // TODO: Split this header into smaller files ufc_geometry_.h or ufc_geometry__d.h? /// --- Local reference cell entity relations by UFC conventions --- static const unsigned int interval_facet_vertices[2][2] = {{0}, {1}}; static const unsigned int triangle_facet_vertices[3][2] = {{1, 2}, {0, 2}, {0, 1}}; static const unsigned int tetrahedron_facet_vertices[4][3] = {{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}}; static const unsigned int tetrahedron_facet_edge_vertices[4][3][2] = { {{2, 3}, {1, 3}, {1, 2}}, {{2, 3}, {0, 3}, {0, 2}}, {{1, 3}, {0, 3}, {0, 1}}, {{1, 2}, {0, 2}, {0, 1}}, }; ///--- Computation of Jacobian matrices --- /// Compute Jacobian J for interval embedded in R^1 inline void compute_jacobian_interval_1d(double J[1], const double vertex_coordinates[2]) { J[0] = vertex_coordinates[1] - vertex_coordinates[0]; } /// Compute Jacobian J for interval embedded in R^2 inline void compute_jacobian_interval_2d(double J[2], const double vertex_coordinates[4]) { J[0] = vertex_coordinates[2] - vertex_coordinates[0]; J[1] = vertex_coordinates[3] - vertex_coordinates[1]; } /// Compute Jacobian J for interval embedded in R^3 inline void compute_jacobian_interval_3d(double J[3], const double vertex_coordinates[6]) { J[0] = vertex_coordinates[3] - vertex_coordinates[0]; J[1] = vertex_coordinates[4] - vertex_coordinates[1]; J[2] = vertex_coordinates[5] - vertex_coordinates[2]; } /// Compute Jacobian J for triangle embedded in R^2 inline void compute_jacobian_triangle_2d(double J[4], const double vertex_coordinates[6]) { J[0] = vertex_coordinates[2] - vertex_coordinates[0]; J[1] = vertex_coordinates[4] - vertex_coordinates[0]; J[2] = vertex_coordinates[3] - vertex_coordinates[1]; J[3] = vertex_coordinates[5] - vertex_coordinates[1]; } /// Compute Jacobian J for triangle embedded in R^3 inline void compute_jacobian_triangle_3d(double J[6], const double vertex_coordinates[9]) { J[0] = vertex_coordinates[3] - vertex_coordinates[0]; J[1] = vertex_coordinates[6] - vertex_coordinates[0]; J[2] = vertex_coordinates[4] - vertex_coordinates[1]; J[3] = vertex_coordinates[7] - vertex_coordinates[1]; J[4] = vertex_coordinates[5] - vertex_coordinates[2]; J[5] = vertex_coordinates[8] - vertex_coordinates[2]; } /// Compute Jacobian J for tetrahedron embedded in R^3 inline void compute_jacobian_tetrahedron_3d(double J[9], const double vertex_coordinates[12]) { J[0] = vertex_coordinates[3] - vertex_coordinates[0]; J[1] = vertex_coordinates[6] - vertex_coordinates[0]; J[2] = vertex_coordinates[9] - vertex_coordinates[0]; J[3] = vertex_coordinates[4] - vertex_coordinates[1]; J[4] = vertex_coordinates[7] - vertex_coordinates[1]; J[5] = vertex_coordinates[10] - vertex_coordinates[1]; J[6] = vertex_coordinates[5] - vertex_coordinates[2]; J[7] = vertex_coordinates[8] - vertex_coordinates[2]; J[8] = vertex_coordinates[11] - vertex_coordinates[2]; } //--- Computation of Jacobian inverses --- // TODO: Remove this when ffc is updated to use the NEW ones below /// Compute Jacobian inverse K for interval embedded in R^1 inline void compute_jacobian_inverse_interval_1d(double* K, double& det, const double* J) { det = J[0]; K[0] = 1.0 / det; } /// Compute Jacobian (pseudo)inverse K for interval embedded in R^2 inline void compute_jacobian_inverse_interval_2d(double* K, double& det, const double* J) { const double det2 = J[0]*J[0] + J[1]*J[1]; det = std::sqrt(det2); K[0] = J[0] / det2; K[1] = J[1] / det2; } /// Compute Jacobian (pseudo)inverse K for interval embedded in R^3 inline void compute_jacobian_inverse_interval_3d(double* K, double& det, const double* J) { // TODO: Move computation of det to a separate function, det is often needed when K is not const double det2 = J[0]*J[0] + J[1]*J[1] + J[2]*J[2]; det = std::sqrt(det2); K[0] = J[0] / det2; K[1] = J[1] / det2; K[2] = J[2] / det2; } /// Compute Jacobian inverse K for triangle embedded in R^2 inline void compute_jacobian_inverse_triangle_2d(double* K, double& det, const double* J) { det = J[0]*J[3] - J[1]*J[2]; K[0] = J[3] / det; K[1] = -J[1] / det; K[2] = -J[2] / det; K[3] = J[0] / det; } /// Compute Jacobian (pseudo)inverse K for triangle embedded in R^3 inline void compute_jacobian_inverse_triangle_3d(double* K, double& det, const double* J) { const double d_0 = J[2]*J[5] - J[4]*J[3]; const double d_1 = J[4]*J[1] - J[0]*J[5]; const double d_2 = J[0]*J[3] - J[2]*J[1]; const double c_0 = J[0]*J[0] + J[2]*J[2] + J[4]*J[4]; const double c_1 = J[1]*J[1] + J[3]*J[3] + J[5]*J[5]; const double c_2 = J[0]*J[1] + J[2]*J[3] + J[4]*J[5]; const double den = c_0*c_1 - c_2*c_2; const double det2 = d_0*d_0 + d_1*d_1 + d_2*d_2; det = std::sqrt(det2); K[0] = (J[0]*c_1 - J[1]*c_2) / den; K[1] = (J[2]*c_1 - J[3]*c_2) / den; K[2] = (J[4]*c_1 - J[5]*c_2) / den; K[3] = (J[1]*c_0 - J[0]*c_2) / den; K[4] = (J[3]*c_0 - J[2]*c_2) / den; K[5] = (J[5]*c_0 - J[4]*c_2) / den; } /// Compute Jacobian inverse K for tetrahedron embedded in R^3 inline void compute_jacobian_inverse_tetrahedron_3d(double* K, double& det, const double* J) { const double d_00 = J[4]*J[8] - J[5]*J[7]; const double d_01 = J[5]*J[6] - J[3]*J[8]; const double d_02 = J[3]*J[7] - J[4]*J[6]; const double d_10 = J[2]*J[7] - J[1]*J[8]; const double d_11 = J[0]*J[8] - J[2]*J[6]; const double d_12 = J[1]*J[6] - J[0]*J[7]; const double d_20 = J[1]*J[5] - J[2]*J[4]; const double d_21 = J[2]*J[3] - J[0]*J[5]; const double d_22 = J[0]*J[4] - J[1]*J[3]; det = J[0]*d_00 + J[3]*d_10 + J[6]*d_20; K[0] = d_00 / det; K[1] = d_10 / det; K[2] = d_20 / det; K[3] = d_01 / det; K[4] = d_11 / det; K[5] = d_21 / det; K[6] = d_02 / det; K[7] = d_12 / det; K[8] = d_22 / det; } //--- NEW Computation of Jacobian (sub)determinants --- /// Compute Jacobian determinant for interval embedded in R^1 inline void compute_jacobian_determinants_interval_1d(double & det, const double J[1]) { det = J[0]; } /// Compute Jacobian (pseudo)determinants for interval embedded in R^2 inline void compute_jacobian_determinants_interval_2d(double & det2, double & det, const double J[2]) { det2 = J[0]*J[0] + J[1]*J[1]; det = std::sqrt(det2); } /// Compute Jacobian (pseudo)determinants for interval embedded in R^3 inline void compute_jacobian_determinants_interval_3d(double & det2, double & det, const double J[3]) { det2 = J[0]*J[0] + J[1]*J[1] + J[2]*J[2]; det = std::sqrt(det2); } /// Compute Jacobian determinant for triangle embedded in R^2 inline void compute_jacobian_determinants_triangle_2d(double & det, const double J[4]) { det = J[0]*J[3] - J[1]*J[2]; } /// Compute Jacobian (pseudo)determinants for triangle embedded in R^3 inline void compute_jacobian_determinants_triangle_3d(double & den, double & det2, double & det, double c[3], const double J[6]) { const double d_0 = J[2]*J[5] - J[4]*J[3]; const double d_1 = J[4]*J[1] - J[0]*J[5]; const double d_2 = J[0]*J[3] - J[2]*J[1]; c[0] = J[0]*J[0] + J[2]*J[2] + J[4]*J[4]; c[1] = J[1]*J[1] + J[3]*J[3] + J[5]*J[5]; c[2] = J[0]*J[1] + J[2]*J[3] + J[4]*J[5]; den = c[0]*c[1] - c[2]*c[2]; det2 = d_0*d_0 + d_1*d_1 + d_2*d_2; det = std::sqrt(det2); } /// Compute Jacobian determinants for tetrahedron embedded in R^3 inline void compute_jacobian_determinants_tetrahedron_3d(double & det, double d[9], const double J[9]) { d[0*3 + 0] = J[4]*J[8] - J[5]*J[7]; d[0*3 + 1] = J[5]*J[6] - J[3]*J[8]; d[0*3 + 2] = J[3]*J[7] - J[4]*J[6]; d[1*3 + 0] = J[2]*J[7] - J[1]*J[8]; d[1*3 + 1] = J[0]*J[8] - J[2]*J[6]; d[1*3 + 2] = J[1]*J[6] - J[0]*J[7]; d[2*3 + 0] = J[1]*J[5] - J[2]*J[4]; d[2*3 + 1] = J[2]*J[3] - J[0]*J[5]; d[2*3 + 2] = J[0]*J[4] - J[1]*J[3]; det = J[0]*d[0*3 + 0] + J[3]*d[1*3 + 0] + J[6]*d[2*3 + 0]; } //--- NEW Computation of Jacobian inverses --- /// Compute Jacobian inverse K for interval embedded in R^1 inline void new_compute_jacobian_inverse_interval_1d(double K[1], double det) { K[0] = 1.0 / det; } /// Compute Jacobian (pseudo)inverse K for interval embedded in R^2 inline void new_compute_jacobian_inverse_interval_2d(double K[2], double det2, const double J[2]) { K[0] = J[0] / det2; K[1] = J[1] / det2; } /// Compute Jacobian (pseudo)inverse K for interval embedded in R^3 inline void new_compute_jacobian_inverse_interval_3d(double K[3], double det2, const double J[3]) { K[0] = J[0] / det2; K[1] = J[1] / det2; K[2] = J[2] / det2; } /// Compute Jacobian inverse K for triangle embedded in R^2 inline void new_compute_jacobian_inverse_triangle_2d(double K[4], double det, const double J[4]) { K[0] = J[3] / det; K[1] = -J[1] / det; K[2] = -J[2] / det; K[3] = J[0] / det; } /// Compute Jacobian (pseudo)inverse K for triangle embedded in R^3 inline void new_compute_jacobian_inverse_triangle_3d(double K[6], double den, const double c[3], const double J[6]) { K[0] = (J[0]*c[1] - J[1]*c[2]) / den; K[1] = (J[2]*c[1] - J[3]*c[2]) / den; K[2] = (J[4]*c[1] - J[5]*c[2]) / den; K[3] = (J[1]*c[0] - J[0]*c[2]) / den; K[4] = (J[3]*c[0] - J[2]*c[2]) / den; K[5] = (J[5]*c[0] - J[4]*c[2]) / den; } /// Compute Jacobian inverse K for tetrahedron embedded in R^3 inline void new_compute_jacobian_inverse_tetrahedron_3d(double K[9], double det, const double d[9]) { K[0] = d[0*3 + 0] / det; K[1] = d[1*3 + 0] / det; K[2] = d[2*3 + 0] / det; K[3] = d[0*3 + 1] / det; K[4] = d[1*3 + 1] / det; K[5] = d[2*3 + 1] / det; K[6] = d[0*3 + 2] / det; K[7] = d[1*3 + 2] / det; K[8] = d[2*3 + 2] / det; } // --- Computation of edge, face, facet scaling factors /// Compute edge scaling factors for triangle embedded in R^2 inline void compute_edge_scaling_factors_triangle_2d(double dx[2], const double vertex_coordinates[6], std::size_t facet) { // Get vertices on edge const unsigned int v0 = triangle_facet_vertices[facet][0]; const unsigned int v1 = triangle_facet_vertices[facet][1]; // Compute scale factor (length of edge scaled by length of reference interval) dx[0] = vertex_coordinates[2*v1 + 0] - vertex_coordinates[2*v0 + 0]; dx[1] = vertex_coordinates[2*v1 + 1] - vertex_coordinates[2*v0 + 1]; } /// Compute facet scaling factor for triangle embedded in R^2 inline void compute_facet_scaling_factor_triangle_2d(double & det, const double dx[2]) { det = std::sqrt(dx[0]*dx[0] + dx[1]*dx[1]); } /// Compute edge scaling factors for triangle embedded in R^3 inline void compute_edge_scaling_factors_triangle_3d(double dx[3], const double vertex_coordinates[9], std::size_t facet) { // Get vertices on edge const unsigned int v0 = triangle_facet_vertices[facet][0]; const unsigned int v1 = triangle_facet_vertices[facet][1]; // Compute scale factor (length of edge scaled by length of reference interval) dx[0] = vertex_coordinates[3*v1 + 0] - vertex_coordinates[3*v0 + 0]; dx[1] = vertex_coordinates[3*v1 + 1] - vertex_coordinates[3*v0 + 1]; dx[2] = vertex_coordinates[3*v1 + 2] - vertex_coordinates[3*v0 + 2]; } /// Compute facet scaling factor for triangle embedded in R^3 inline void compute_facet_scaling_factor_triangle_3d(double & det, const double dx[3]) { det = std::sqrt(dx[0]*dx[0] + dx[1]*dx[1] + dx[2]*dx[2]); } /// Compute face scaling factors for tetrahedron embedded in R^3 inline void compute_face_scaling_factors_tetrahedron_3d(double a[3], const double vertex_coordinates[12], std::size_t facet) { // Get vertices on face const unsigned int v0 = tetrahedron_facet_vertices[facet][0]; const unsigned int v1 = tetrahedron_facet_vertices[facet][1]; const unsigned int v2 = tetrahedron_facet_vertices[facet][2]; // Compute scale factor (area of face scaled by area of reference triangle) a[0] = (vertex_coordinates[3*v0 + 1]*vertex_coordinates[3*v1 + 2] + vertex_coordinates[3*v0 + 2]*vertex_coordinates[3*v2 + 1] + vertex_coordinates[3*v1 + 1]*vertex_coordinates[3*v2 + 2]) - (vertex_coordinates[3*v2 + 1]*vertex_coordinates[3*v1 + 2] + vertex_coordinates[3*v2 + 2]*vertex_coordinates[3*v0 + 1] + vertex_coordinates[3*v1 + 1]*vertex_coordinates[3*v0 + 2]); a[1] = (vertex_coordinates[3*v0 + 2]*vertex_coordinates[3*v1 + 0] + vertex_coordinates[3*v0 + 0]*vertex_coordinates[3*v2 + 2] + vertex_coordinates[3*v1 + 2]*vertex_coordinates[3*v2 + 0]) - (vertex_coordinates[3*v2 + 2]*vertex_coordinates[3*v1 + 0] + vertex_coordinates[3*v2 + 0]*vertex_coordinates[3*v0 + 2] + vertex_coordinates[3*v1 + 2]*vertex_coordinates[3*v0 + 0]); a[2] = (vertex_coordinates[3*v0 + 0]*vertex_coordinates[3*v1 + 1] + vertex_coordinates[3*v0 + 1]*vertex_coordinates[3*v2 + 0] + vertex_coordinates[3*v1 + 0]*vertex_coordinates[3*v2 + 1]) - (vertex_coordinates[3*v2 + 0]*vertex_coordinates[3*v1 + 1] + vertex_coordinates[3*v2 + 1]*vertex_coordinates[3*v0 + 0] + vertex_coordinates[3*v1 + 0]*vertex_coordinates[3*v0 + 1]); } /// Compute facet scaling factor for tetrahedron embedded in R^3 inline void compute_facet_scaling_factor_tetrahedron_3d(double & det, const double a[3]) { det = std::sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); } ///--- Compute facet normal directions --- /// Compute facet direction for interval embedded in R^1 inline void compute_facet_normal_direction_interval_1d(bool & direction, const double vertex_coordinates[2], std::size_t facet) { direction = facet == 0 ? vertex_coordinates[0] > vertex_coordinates[1] : vertex_coordinates[1] > vertex_coordinates[0]; } /// Compute facet direction for triangle embedded in R^2 inline void compute_facet_normal_direction_triangle_2d(bool & direction, const double vertex_coordinates[6], const double dx[2], std::size_t facet) { const unsigned int v0 = triangle_facet_vertices[facet][0]; direction = dx[1]*(vertex_coordinates[2*facet ] - vertex_coordinates[2*v0 ]) - dx[0]*(vertex_coordinates[2*facet + 1] - vertex_coordinates[2*v0 + 1]) < 0; } /// Compute facet direction for tetrahedron embedded in R^3 inline void compute_facet_normal_direction_tetrahedron_3d(bool & direction, const double vertex_coordinates[9], const double a[3], std::size_t facet) { const unsigned int v0 = tetrahedron_facet_vertices[facet][0]; direction = a[0]*(vertex_coordinates[3*facet ] - vertex_coordinates[3*v0 ]) + a[1]*(vertex_coordinates[3*facet + 1] - vertex_coordinates[3*v0 + 1]) + a[2]*(vertex_coordinates[3*facet + 2] - vertex_coordinates[3*v0 + 2]) < 0; } ///--- Compute facet normal vectors --- /// Compute facet normal for interval embedded in R^1 inline void compute_facet_normal_interval_1d(double n[1], bool direction) { // Facet normals are 1.0 or -1.0: (-1.0) <-- X------X --> (1.0) n[0] = direction ? 1.0 : -1.0; } /// Compute facet normal for interval embedded in R^2 inline void compute_facet_normal_interval_2d(double n[2], const double vertex_coordinates[4], std::size_t facet) { if (facet == 0) { n[0] = vertex_coordinates[0] - vertex_coordinates[2]; n[1] = vertex_coordinates[1] - vertex_coordinates[3]; } else { n[0] = vertex_coordinates[2] - vertex_coordinates[0]; n[1] = vertex_coordinates[3] - vertex_coordinates[1]; } const double n_length = std::sqrt(n[0]*n[0] + n[1]*n[1]); n[0] /= n_length; n[1] /= n_length; } /// Compute facet normal for interval embedded in R^3 inline void compute_facet_normal_interval_3d(double n[3], const double vertex_coordinates[6], std::size_t facet) { if (facet == 0) { n[0] = vertex_coordinates[0] - vertex_coordinates[3]; n[1] = vertex_coordinates[1] - vertex_coordinates[4]; n[1] = vertex_coordinates[2] - vertex_coordinates[5]; } else { n[0] = vertex_coordinates[3] - vertex_coordinates[0]; n[1] = vertex_coordinates[4] - vertex_coordinates[1]; n[1] = vertex_coordinates[5] - vertex_coordinates[2]; } const double n_length = std::sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]); n[0] /= n_length; n[1] /= n_length; n[2] /= n_length; } /// Compute facet normal for triangle embedded in R^2 inline void compute_facet_normal_triangle_2d(double n[2], const double dx[2], const double det, bool direction) { // Compute facet normals from the facet scale factor constants n[0] = direction ? dx[1] / det : -dx[1] / det; n[1] = direction ? -dx[0] / det : dx[0] / det; } /// Compute facet normal for triangle embedded in R^3 inline void compute_facet_normal_triangle_3d(double n[3], const double vertex_coordinates[6], std::size_t facet) { // Compute facet normal for triangles in 3D const unsigned int vertex0 = facet; // Get coordinates corresponding the vertex opposite this const unsigned int vertex1 = triangle_facet_vertices[facet][0]; const unsigned int vertex2 = triangle_facet_vertices[facet][1]; // Define vectors n = (p2 - p0) and t = normalized (p2 - p1) n[0] = vertex_coordinates[3*vertex2 + 0] - vertex_coordinates[3*vertex0 + 0]; n[1] = vertex_coordinates[3*vertex2 + 1] - vertex_coordinates[3*vertex0 + 1]; n[2] = vertex_coordinates[3*vertex2 + 2] - vertex_coordinates[3*vertex0 + 2]; double t0 = vertex_coordinates[3*vertex2 + 0] - vertex_coordinates[3*vertex1 + 0]; double t1 = vertex_coordinates[3*vertex2 + 1] - vertex_coordinates[3*vertex1 + 1]; double t2 = vertex_coordinates[3*vertex2 + 2] - vertex_coordinates[3*vertex1 + 2]; const double t_length = std::sqrt(t0*t0 + t1*t1 + t2*t2); t0 /= t_length; t1 /= t_length; t2 /= t_length; // Subtract, the projection of (p2 - p0) onto (p2 - p1), from (p2 - p0) const double ndott = t0*n[0] + t1*n[1] + t2*n[2]; n[0] -= ndott*t0; n[1] -= ndott*t1; n[2] -= ndott*t2; const double n_length = std::sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]); // Normalize n[0] /= n_length; n[1] /= n_length; n[2] /= n_length; } /// Compute facet normal for tetrahedron embedded in R^3 inline void compute_facet_normal_tetrahedron_3d(double n[3], const double a[3], const double det, bool direction) { // Compute facet normals from the facet scale factor constants n[0] = direction ? a[0] / det : -a[0] / det; n[1] = direction ? a[1] / det : -a[1] / det; n[2] = direction ? a[2] / det : -a[2] / det; } ///--- Compute circumradius --- /// Compute circumradius for interval embedded in R^1 inline void compute_circumradius_interval_1d(double & circumradius, double volume) { // Compute circumradius; in 1D it is equal to half the cell length circumradius = volume / 2.0; } /// Compute circumradius for interval embedded in R^2 inline void compute_circumradius_interval_2d(double & circumradius, double volume) { // Compute circumradius of interval in 2D (1/2 volume) circumradius = volume / 2.0; } /// Compute circumradius for interval embedded in R^3 inline void compute_circumradius_interval_3d(double & circumradius, double volume) { // Compute circumradius of interval in 3D (1/2 volume) circumradius = volume / 2.0; } /// Compute circumradius for triangle embedded in R^2 inline void compute_circumradius_triangle_2d(double & circumradius, const double vertex_coordinates[6], const double J[4], double volume) { // Compute circumradius of triangle in 2D const double v1v2 = std::sqrt( (vertex_coordinates[4] - vertex_coordinates[2])*(vertex_coordinates[4] - vertex_coordinates[2]) + (vertex_coordinates[5] - vertex_coordinates[3])*(vertex_coordinates[5] - vertex_coordinates[3]) ); const double v0v2 = std::sqrt(J[3]*J[3] + J[1]*J[1]); const double v0v1 = std::sqrt(J[0]*J[0] + J[2]*J[2]); circumradius = 0.25*(v1v2*v0v2*v0v1) / volume; } /// Compute circumradius for triangle embedded in R^3 inline void compute_circumradius_triangle_3d(double & circumradius, const double vertex_coordinates[9], const double J[6], double volume) { // Compute circumradius of triangle in 3D const double v1v2 = std::sqrt( (vertex_coordinates[6] - vertex_coordinates[3])*(vertex_coordinates[6] - vertex_coordinates[3]) + (vertex_coordinates[7] - vertex_coordinates[4])*(vertex_coordinates[7] - vertex_coordinates[4]) + (vertex_coordinates[8] - vertex_coordinates[5])*(vertex_coordinates[8] - vertex_coordinates[5])); const double v0v2 = std::sqrt( J[3]*J[3] + J[1]*J[1] + J[5]*J[5]); const double v0v1 = std::sqrt( J[0]*J[0] + J[2]*J[2] + J[4]*J[4]); circumradius = 0.25*(v1v2*v0v2*v0v1) / volume; } /// Compute circumradius for tetrahedron embedded in R^3 inline void compute_circumradius_tetrahedron_3d(double & circumradius, const double vertex_coordinates[12], const double J[9], double volume) { // Compute circumradius const double v1v2 = std::sqrt( (vertex_coordinates[6] - vertex_coordinates[3])*(vertex_coordinates[6] - vertex_coordinates[3]) + (vertex_coordinates[7] - vertex_coordinates[4])*(vertex_coordinates[7] - vertex_coordinates[4]) + (vertex_coordinates[8] - vertex_coordinates[5])*(vertex_coordinates[8] - vertex_coordinates[5]) ); const double v0v2 = std::sqrt(J[1]*J[1] + J[4]*J[4] + J[7]*J[7]); const double v0v1 = std::sqrt(J[0]*J[0] + J[3]*J[3] + J[6]*J[6]); const double v0v3 = std::sqrt(J[2]*J[2] + J[5]*J[5] + J[8]*J[8]); const double v1v3 = std::sqrt( (vertex_coordinates[ 9] - vertex_coordinates[3])*(vertex_coordinates[ 9] - vertex_coordinates[3]) + (vertex_coordinates[10] - vertex_coordinates[4])*(vertex_coordinates[10] - vertex_coordinates[4]) + (vertex_coordinates[11] - vertex_coordinates[5])*(vertex_coordinates[11] - vertex_coordinates[5]) ); const double v2v3 = std::sqrt( (vertex_coordinates[ 9] - vertex_coordinates[6])*(vertex_coordinates[ 9] - vertex_coordinates[6]) + (vertex_coordinates[10] - vertex_coordinates[7])*(vertex_coordinates[10] - vertex_coordinates[7]) + (vertex_coordinates[11] - vertex_coordinates[8])*(vertex_coordinates[11] - vertex_coordinates[8]) ); const double la = v1v2*v0v3; const double lb = v0v2*v1v3; const double lc = v0v1*v2v3; const double s = 0.5*(la+lb+lc); const double area = std::sqrt(s*(s-la)*(s-lb)*(s-lc)); circumradius = area / (6.0*volume); } ///--- Compute max facet edge lengths --- /// Compute min edge length in facet of tetrahedron embedded in R^3 inline void compute_min_facet_edge_length_tetrahedron_3d(double & min_edge_length, unsigned int facet, const double vertex_coordinates[12]) { // TODO: Extract compute_facet_edge_lengths_tetrahedron_3d(), reuse between min/max functions double edge_lengths_sqr[3]; for (unsigned int edge = 0; edge < 3; ++edge) { const unsigned int vertex0 = tetrahedron_facet_edge_vertices[facet][edge][0]; const unsigned int vertex1 = tetrahedron_facet_edge_vertices[facet][edge][1]; edge_lengths_sqr[edge] = (vertex_coordinates[3*vertex1 + 0] - vertex_coordinates[3*vertex0 + 0])*(vertex_coordinates[3*vertex1 + 0] - vertex_coordinates[3*vertex0 + 0]) + (vertex_coordinates[3*vertex1 + 1] - vertex_coordinates[3*vertex0 + 1])*(vertex_coordinates[3*vertex1 + 1] - vertex_coordinates[3*vertex0 + 1]) + (vertex_coordinates[3*vertex1 + 2] - vertex_coordinates[3*vertex0 + 2])*(vertex_coordinates[3*vertex1 + 2] - vertex_coordinates[3*vertex0 + 2]); } min_edge_length = std::sqrt(std::min(std::min(edge_lengths_sqr[1], edge_lengths_sqr[1]), edge_lengths_sqr[2])); } ///--- Compute max facet edge lengths --- /// Compute max edge length in facet of tetrahedron embedded in R^3 inline void compute_max_facet_edge_length_tetrahedron_3d(double & max_edge_length, unsigned int facet, const double vertex_coordinates[12]) { // TODO: Extract compute_facet_edge_lengths_tetrahedron_3d(), reuse between min/max functions double edge_lengths_sqr[3]; for (unsigned int edge = 0; edge < 3; ++edge) { const unsigned int vertex0 = tetrahedron_facet_edge_vertices[facet][edge][0]; const unsigned int vertex1 = tetrahedron_facet_edge_vertices[facet][edge][1]; edge_lengths_sqr[edge] = (vertex_coordinates[3*vertex1 + 0] - vertex_coordinates[3*vertex0 + 0])*(vertex_coordinates[3*vertex1 + 0] - vertex_coordinates[3*vertex0 + 0]) + (vertex_coordinates[3*vertex1 + 1] - vertex_coordinates[3*vertex0 + 1])*(vertex_coordinates[3*vertex1 + 1] - vertex_coordinates[3*vertex0 + 1]) + (vertex_coordinates[3*vertex1 + 2] - vertex_coordinates[3*vertex0 + 2])*(vertex_coordinates[3*vertex1 + 2] - vertex_coordinates[3*vertex0 + 2]); } max_edge_length = std::sqrt(std::max(std::max(edge_lengths_sqr[0], edge_lengths_sqr[1]), edge_lengths_sqr[2])); } #endif ufc-2.3.0/src/utils/000077500000000000000000000000001226277264200142325ustar00rootroot00000000000000ufc-2.3.0/src/utils/python/000077500000000000000000000000001226277264200155535ustar00rootroot00000000000000ufc-2.3.0/src/utils/python/ufc_benchmark/000077500000000000000000000000001226277264200203425ustar00rootroot00000000000000ufc-2.3.0/src/utils/python/ufc_benchmark/Makefile000066400000000000000000000017441226277264200220100ustar00rootroot00000000000000# # An overly complicated makefile for compiling a swig module. # MODULENAME=ufc_benchmark CXX=g++ ufcinclude=-I../../../ufc # Python location and version PYTHONROOT:=$(shell python -c 'import sys; print sys.prefix') PYTHONVER:=$(shell python -c 'import sys; print sys.version[:3]') all: _$(MODULENAME).so echo Done. # link module _$(MODULENAME).so: $(MODULENAME)_wrap.o $(MODULENAME).o $(CXX) -shared -o _$(MODULENAME).so $(MODULENAME)_wrap.o $(MODULENAME).o # compile wrapper $(MODULENAME)_wrap.o: $(MODULENAME)_wrap.cxx $(CXX) -I$(PYTHONROOT)/include/python$(PYTHONVER) -o $@ -c $< # generate wrapper $(MODULENAME)_wrap.cxx: $(MODULENAME).i $(MODULENAME).h swig -c++ -python $(ufcinclude) $(MODULENAME).i # compile module code $(MODULENAME).o: *.h *.cpp $(CXX) -c -o $(MODULENAME).o $(MODULENAME).cpp clean: rm -f $(MODULENAME).o rm -f $(MODULENAME).py rm -f $(MODULENAME).pyc rm -f _$(MODULENAME).so rm -f $(MODULENAME)_wrap.cxx rm -f $(MODULENAME)_wrap.o rm -rf build ufc-2.3.0/src/utils/python/ufc_benchmark/setup.py000066400000000000000000000016671226277264200220660ustar00rootroot00000000000000#!/usr/bin/env python from distutils.core import setup from distutils.core import Extension import os # the buggy swig-support in distutils doesn't manage to invoke g++, uses gcc... os.system("make ufc_benchmark_wrap.cxx") extension = Extension('_ufc_benchmark', ['ufc_benchmark.cpp', 'ufc_benchmark_wrap.cxx'], language="c++", include_dirs=["../../../ufc"]) setup(### metadata: name = 'ufc_benchmark', version = '1.1.2', author = 'Martin Sandve Alnes', author_email = 'martinal@simula.no', maintainer = 'Martin Sandve Alnes', maintainer_email = 'martinal@simula.no', url = 'http://www.fenicsproject.org', description = 'Benchmark utility for UFC implementations.', download_url = 'https://bitbucket/fenics-project/ufc', ### contents: py_modules = ['ufc_benchmark'], ext_modules = [extension], ) ufc-2.3.0/src/utils/python/ufc_benchmark/ufc_benchmark.cpp000066400000000000000000000241611226277264200236410ustar00rootroot00000000000000// This is utility code for UFC (Unified Form-assembly Code) v. 2.3.0. // This code is released into the public domain. // // The FEniCS Project (http://www.fenicsproject.org/) 2006-2014. #include #include using std::cout; using std::endl; using std::vector; #include #define TMIN 3.0 #define MMIN 1000 #include "ufc_data.h" #include "ufc_reference_cell.h" #include "ufc_benchmark.h" clock_t __tic_time; void tic() { __tic_time = clock(); } double toc() { clock_t __toc_time = clock(); double elapsed_time = ((double) (__toc_time - __tic_time)) / CLOCKS_PER_SEC; return elapsed_time; } // Adaptive timing: make sure we run for at least TMIN to get reliable results double time_tabulate_tensor(ufc::cell_integral& integral, double *A, const double * const * w, const ufc::cell & c) { std::size_t M = MMIN; while ( true ) { tic(); for (std::size_t i = 0; i < M; i++) { integral.tabulate_tensor(A, w, c); } double t = toc(); if ( t >= TMIN ) return t / static_cast(M); M *= 10; cout << "Elapsed time too short, increasing number of iterations to" << M << endl; } return 0.0; } // Adaptive timing: make sure we run for at least TMIN to get reliable results double time_tabulate_tensor(ufc::exterior_facet_integral& integral, double *A, const double * const * w, const ufc::cell & c, std::size_t facet) { std::size_t M = MMIN; while ( true ) { tic(); for (std::size_t i = 0; i < M; i++) { integral.tabulate_tensor(A, w, c, facet); } double t = toc(); if ( t >= TMIN ) return t / static_cast(M); M *= 10; cout << "Elapsed time too short, increasing number of iterations to" << M << endl; } return 0.0; } // Benchmark all integrals of a form. vector< vector > benchmark(const ufc::form & form, bool print_tensor) { // construct and allocate some stuff ufc::ufc_data data(form); // create a reference cell geometry ufc::reference_cell c(data.elements[0]->cell_shape()); // data structures for times vector cell_times(form.num_cell_domains()); vector exterior_facet_times(form.num_exterior_facet_domains()); vector interior_facet_times(form.num_interior_facet_domains()); // benchmark all cell integrals for(unsigned i = 0; i < form.num_cell_domains(); i++) { cell_times[i] = time_tabulate_tensor(*data.cell_domains[i], data.A, data.w, c); if(print_tensor) { cout << "Cell element tensor " << i << ":" << endl; data.print_tensor(); cout << endl; } } // benchmark all exterior facet integrals for(unsigned i = 0; i < form.num_exterior_facet_domains(); i++) { std::size_t facet = 0; // TODO: would it be interesting to time all facets? exterior_facet_times[i] = time_tabulate_tensor(*data.exterior_facet_domains[i], data.A, data.w, c, facet); if(print_tensor) { cout << "Exterior facet element tensor " << i << ":" << endl; data.print_tensor(); cout << endl; } } // benchmark all interior facet integrals /* // TODO: If somebody needs this, please implement it! Need two cells, and larger A. for(unsigned i = 0; i < form.num_interior_facet_domains(); i++) { std::size_t facet = 0; // TODO: would it be interesting to time all facets? interior_facet_times[i] = time_tabulate_tensor(*data.interior_facet_domains[i], data.A, data.w, c, facet); if(print_tensor) { cout << "Interior facet element tensor " << i << ":" << endl; data.print_tensor(); cout << endl; } } */ vector< vector > result(3); result[0] = cell_times; result[1] = exterior_facet_times; result[2] = interior_facet_times; return result; } vector< vector > tabulate_cell_tensor(const ufc::form & form, vector< vector > w, int domain) { ufc::ufc_data data(form); // copy w to the appropriate array if(data.num_coefficients != w.size()) throw std::runtime_error("Wrong number of coefficients"); for(unsigned i=0; icell_shape()); // tabulate the tensor data.cell_integrals[domain]->tabulate_tensor(data.A, data.w, c); // copy element tensor to stl-structure for easy returning to python (should perhaps rather use numpy and some typemaps, but I'm lazy) vector< vector > A; if(data.rank == 2) { A.resize(data.dimensions[0]); for(unsigned i=0; i > tabulate_cell_integral(const boost::shared_ptr form, std::vector< std::vector > w, ufc::cell cell, int domain) { ufc::ufc_data data(*form); // copy w to the appropriate array if(data.num_coefficients != w.size()) throw std::runtime_error("Wrong number of coefficients"); for(unsigned i=0; itabulate_tensor(data.A, data.w, cell); // copy element tensor to stl-structure for easy returning to python (should perhaps rather use numpy and some typemaps, but I'm lazy) vector< vector > A; if(data.rank == 2) { A.resize(data.dimensions[0]); for(unsigned i=0; i > tabulate_exterior_facet_integral(const boost::shared_ptr form, std::vector< std::vector > w, ufc::cell& cell, int facet, int domain) { ufc::ufc_data data(*form); // copy w to the appropriate array if(data.num_coefficients != w.size()) throw std::runtime_error("Wrong number of coefficients"); for(unsigned i=0; itabulate_tensor(data.A, data.w, cell, facet); // copy element tensor to stl-structure for easy returning to python (should perhaps rather use numpy and some typemaps, but I'm lazy) vector< vector > A; if(data.rank == 2) { A.resize(data.dimensions[0]); for(unsigned i=0; i > tabulate_interior_facet_integral(const boost::shared_ptr form, std::vector< std::vector > macro_w,\ ufc::cell& cell0, ufc::cell& cell1, int facet_0, int facet_1, int domain) { ufc::ufc_data data(*form); // copy w to the appropriate array if(data.num_coefficients != macro_w.size()) throw std::runtime_error("Wrong number of coefficients"); for(unsigned i=0; itabulate_tensor(data.macro_A, data.macro_w, cell0, cell1, facet_0, facet_1); // copy element tensor to stl-structure for easy returning to python (should perhaps rather use numpy and some typemaps, but I'm lazy) vector< vector > A; if(data.rank == 2) { A.resize(2*data.dimensions[0]); for(unsigned i=0; i<2*data.dimensions[0]; i++) { A[i].resize(2*data.dimensions[1]); for(unsigned j=0; j<2*data.dimensions[1]; j++) { A[i][j] = data.macro_A[i*2*data.dimensions[1] + j]; } } } else if(data.rank == 1) { A.resize(2*data.dimensions[0]); for(unsigned i=0; i<2*data.dimensions[0]; i++) { A[i].resize(1); A[i][0] = data.macro_A[i]; } } else if(data.rank == 0) { A.resize(1); A[0].resize(1); A[0][0] = data.macro_A[0]; } else { throw std::runtime_error("rank != 0,1,2 not implemented"); } return A; } ufc-2.3.0/src/utils/python/ufc_benchmark/ufc_benchmark.h000066400000000000000000000046671226277264200233170ustar00rootroot00000000000000// This is utility code for UFC (Unified Form-assembly Code) v 2.3.0. // This code is released into the public domain. // // The FEniCS Project (http://www.fenicsproject.org/) 2006-2014. #ifndef __UFC_BENCHMARK_H__ #define __UFC_BENCHMARK_H__ #include "ufc.h" #include #include /* Benchmark time to run tabulate_tensor for all integrals in a form. * * Uses a reference cell and one-cell mesh, and sets all w_ij = 1.0. */ std::vector< std::vector > benchmark(const ufc::form & form, bool print_tensors); /* Compute one element tensor on the reference cell with the given coefficients. */ std::vector< std::vector > tabulate_cell_tensor(const ufc::form & form, std::vector< std::vector > w, int domain); /* Compute one cell integral. */ std::vector< std::vector > tabulate_cell_integral(const boost::shared_ptr form, std::vector< std::vector > w, ufc::cell cell, int domain); /* Compute one exterior facet integral. */ std::vector< std::vector > tabulate_exterior_facet_integral(const boost::shared_ptr form, std::vector< std::vector > w, ufc::cell& cell, int facet, int domain); /* Compute one interior facet integral. */ std::vector< std::vector > tabulate_interior_facet_integral(const boost::shared_ptr form, std::vector< std::vector > macro_w, ufc::cell& cell0, ufc::cell& cell1, int facet_0, int facet_1, int domain); #endif ufc-2.3.0/src/utils/python/ufc_benchmark/ufc_benchmark.i000066400000000000000000000030251226277264200233030ustar00rootroot00000000000000%module ufc_benchmark // ------------------------ STL stuff %{ #include %} %include stl.i %include std_vector.i %include std_carray.i %template(vector_double) std::vector; %typedef std::vector vector_double; %template(vector_vector_double) std::vector< std::vector >; %typedef std::vector< std::vector > vector_vector_double; %template(vector_std_t) std::vector< std::size_t >; %typedef std::vector< std::size_t > vector_size_t; %template(vector_vector_size_t) std::vector< std::vector< std::size_t > >; %typedef std::vector< std::vector< std::size_t > > vector_vector_size_t; // ------------------------ UFC stuff %import ufc.i %{ #include "ufc.h" #include "ufc_benchmark.h" #include "ufc_reference_cell.h" %} %include "ufc.h" %include "ufc_benchmark.h" %include "ufc_reference_cell.h" // ----------------------- Reference to shared pointer utility %{ class NoDeleter { public: void operator()(ufc::form *) {} }; boost::shared_ptr form_ptr(ufc::form * form) { return boost::shared_ptr(form, NoDeleter()); } %} class NoDeleter { public: void operator()(ufc::form *) {} }; boost::shared_ptr form_ptr(ufc::form * form) { return boost::shared_ptr(form, NoDeleter()); } // ----------------------- Python wrapper for benchmark %pythoncode{ def benchmark_forms(forms, print_tensors): import gc gc.collect() times = [] for f in forms: res = benchmark(f, print_tensors) times.append(tuple(res)) return times } ufc-2.3.0/src/utils/python/ufc_benchmark/ufc_data.h000066400000000000000000000112471226277264200222660ustar00rootroot00000000000000// This is utility code for UFC (Unified Form-assembly Code) v 2.3.0 // This code is released into the public domain. // // The FEniCS Project (http://www.fenicsproject.org/) 2006-2014. #ifndef __UFC_DATA_H__ #define __UFC_DATA_H__ #include #include #include #include namespace ufc { class ufc_data { public: ufc_data(const ufc::form & form): form(form) { // short forms of dimensions rank = form.rank(); num_coefficients = form.num_coefficients(); num_arguments = rank + num_coefficients; // construct all dofmaps and elements dofmaps.resize(num_arguments); elements.resize(num_arguments); dimensions = new unsigned[num_arguments]; for(unsigned i=0; imax_local_dimension(); if(dimensions[i] != elements[i]->space_dimension()) throw std::runtime_error("Mismatching dimensions between finite_elements and dofmaps!"); if(elements[0]->cell_shape() != elements[i]->cell_shape()) throw std::runtime_error("Mismatching cell shapes in elements!"); } // construct all integral objects cell_integrals.resize(form.num_cell_domains()); for(unsigned i=0; i dofmaps; vector< ufc::finite_element * > elements; vector< ufc::cell_integral *> cell_integrals; vector< ufc::exterior_facet_integral *> exterior_facet_integrals; vector< ufc::interior_facet_integral *> interior_facet_integrals; unsigned rank; unsigned num_coefficients; unsigned num_arguments; unsigned A_size; unsigned * dimensions; double * A; double * macro_A; double ** w; double ** macro_w; void print_tensor() { int dim0 = 1; int dim1 = 1; if(rank == 1) { dim1 = dimensions[0]; } if(rank == 2) { dim0 = dimensions[0]; dim1 = dimensions[1]; } cout << "[" << endl; int k=0; for(int ii=0; ii #include namespace ufc { /// Description of a reference cell, for debugging and testing UFC code. class reference_cell: public ufc::cell { public: /// Constructor reference_cell(ufc::shape s) { cell_shape = s; num_entities[0] = 0; num_entities[1] = 0; num_entities[2] = 0; num_entities[3] = 0; // Get topological dimension and number of entities in a cell of this type. switch(s) { case interval: topological_dimension = 1; num_entities[0] = 2; num_entities[1] = 1; break; case triangle: topological_dimension = 2; num_entities[0] = 3; num_entities[1] = 3; num_entities[2] = 1; break; case quadrilateral: topological_dimension = 2; num_entities[0] = 4; num_entities[1] = 4; num_entities[2] = 1; break; case tetrahedron: topological_dimension = 3; num_entities[0] = 4; num_entities[1] = 6; num_entities[2] = 4; num_entities[3] = 1; break; case hexahedron: topological_dimension = 3; num_entities[0] = 8; num_entities[1] = 12; num_entities[2] = 6; num_entities[3] = 1; break; default: throw std::runtime_error("Invalid shape."); } // Assume same geometric dimension. geometric_dimension = topological_dimension; // Fill global indices like we had a single-cell mesh. entity_indices = new std::size_t*[topological_dimension+1]; for(std::size_t i = 0; i <= topological_dimension; i++) { entity_indices[i] = new std::size_t[num_entities[i]]; for(std::size_t j = 0; j < num_entities[i]; j++) { entity_indices[i][j] = j; } } // Allocate an empty array of vertex coordinates. coordinates = new double*[num_entities[0]]; for(std::size_t i = 0; i < num_entities[0]; i++) { coordinates[i] = new double[geometric_dimension]; for(std::size_t j = 0; j < geometric_dimension; j++) { coordinates[i][j] = 0.0; } } // Fill coordinates with reference cell definition. switch(s) { case interval: coordinates[0][0] = 0.0; coordinates[1][0] = 1.0; break; case triangle: coordinates[0][0] = 0.0; coordinates[0][1] = 0.0; coordinates[1][0] = 1.0; coordinates[1][1] = 0.0; coordinates[2][0] = 0.0; coordinates[2][1] = 1.0; break; case quadrilateral: coordinates[0][0] = 0.0; coordinates[0][1] = 0.0; coordinates[1][0] = 1.0; coordinates[1][1] = 0.0; coordinates[2][0] = 1.0; coordinates[2][1] = 1.0; coordinates[3][0] = 0.0; coordinates[3][1] = 1.0; break; case tetrahedron: coordinates[0][0] = 0.0; coordinates[0][1] = 0.0; coordinates[0][2] = 0.0; coordinates[1][0] = 1.0; coordinates[1][1] = 0.0; coordinates[1][2] = 0.0; coordinates[2][0] = 0.0; coordinates[2][1] = 1.0; coordinates[2][2] = 0.0; coordinates[3][0] = 0.0; coordinates[3][1] = 0.0; coordinates[3][2] = 1.0; break; case hexahedron: coordinates[0][0] = 0.0; coordinates[0][1] = 0.0; coordinates[0][2] = 0.0; coordinates[1][0] = 1.0; coordinates[1][1] = 0.0; coordinates[1][2] = 0.0; coordinates[2][0] = 1.0; coordinates[2][1] = 1.0; coordinates[2][2] = 0.0; coordinates[3][0] = 0.0; coordinates[3][1] = 1.0; coordinates[3][2] = 0.0; coordinates[4][0] = 0.0; coordinates[4][1] = 0.0; coordinates[4][2] = 1.0; coordinates[5][0] = 1.0; coordinates[5][1] = 0.0; coordinates[5][2] = 1.0; coordinates[6][0] = 1.0; coordinates[6][1] = 1.0; coordinates[6][2] = 1.0; coordinates[7][0] = 0.0; coordinates[7][1] = 1.0; coordinates[7][2] = 1.0; break; } } /// Destructor virtual ~reference_cell() { for(std::size_t i = 0; i <= topological_dimension; i++) { delete [] entity_indices[i]; } delete [] entity_indices; for(std::size_t i = 0; i < num_entities[0]; i++) { delete [] coordinates[i]; } delete [] coordinates; } /// The number of entities of a particular dimension std::size_t num_entities[4]; }; /// Description of a reference cell, for debugging and testing UFC code. class Cell: public ufc::cell { public: /// Constructor Cell(std::size_t top, std::size_t geo, std::vector< std::vector > coords, std::vector< std::size_t> num_ents): ufc::cell(), num_entities(num_ents) { topological_dimension = top; geometric_dimension = geo; num_entities[0] = coords.size(); // Fill global indices // entity_indices = new std::size_t*[topological_dimension+1]; // for(std::size_t i = 0; i <= topological_dimension; i++) // { // entity_indices[i] = new std::size_t[num_entities[i]]; // for(std::size_t j = 0; j < num_entities[i]; j++) // { // entity_indices[i][j] = j; // } // } for(std::size_t i = 0; i < num_ents.size(); i++) num_entities[i] = num_ents[i]; // Allocate an empty array of vertex coordinates. coordinates = new double*[coords.size()]; for(std::size_t i = 0; i < coords.size(); i++) { coordinates[i] = new double[geometric_dimension]; for(std::size_t j = 0; j < geometric_dimension; j++) { coordinates[i][j] = coords[i][j]; } } } /// Destructor virtual ~Cell() { // for(std::size_t i = 0; i <= topological_dimension; i++) // { // delete [] entity_indices[i]; // } // delete [] entity_indices; for(std::size_t i = 0; i < num_entities[0]; i++) { delete [] coordinates[i]; } delete [] coordinates; } /// The number of entities of a particular dimension std::vector num_entities; }; /// Consistent data for a mesh consisting of a single reference cell, for debugging and testing UFC code. class reference_mesh: public ufc::mesh { public: /// Constructor reference_mesh(ufc::shape s): c(s) { topological_dimension = c.topological_dimension; geometric_dimension = c.geometric_dimension; // Set global number of entities of each topological dimension to that of a single cell. num_entities = new std::size_t[topological_dimension+1]; for(std::size_t i = 0; i <= topological_dimension; i++) { num_entities[i] = c.num_entities[i]; } } /// Destructor virtual ~reference_mesh() { delete [] num_entities; } /// A reference cell, the only cell in this mesh. reference_cell c; }; /// Consistent data for a mesh consisting of a single reference cell, for debugging and testing UFC code. class Mesh: public ufc::mesh { public: /// Constructor Mesh(std::size_t top, std::size_t geo, std::vector ents)//: ufc::mesh() { topological_dimension = top; geometric_dimension = geo; // Set global number of entities of each topological dimension to that of a single cell. num_entities = new std::size_t[topological_dimension+1]; for(std::size_t i = 0; i <= topological_dimension; i++) { num_entities[i] = ents[i]; } } /// Destructor virtual ~Mesh() { delete [] num_entities; } }; } #endif ufc-2.3.0/src/utils/python/ufc_utils/000077500000000000000000000000001226277264200175505ustar00rootroot00000000000000ufc-2.3.0/src/utils/python/ufc_utils/__init__.py000066400000000000000000000067041226277264200216700ustar00rootroot00000000000000"""Code generation format strings for UFC (Unified Form-assembly Code) v. 2.3.0. Three format strings are defined for each of the following UFC classes: function finite_element dofmap cell_integral exterior_facet_integral interior_facet_integral form The strings are named '_header', '_implementation', and '_combined'. The header and implementation contain the definition and declaration respectively, and are meant to be placed in .h and .cpp files, while the combined version is for an implementation within a single .h header. Each string has the following format variables: 'classname', 'members', 'constructor', 'destructor', plus one for each interface function with name equal to the function name. For more information about UFC and the FEniCS Project, visit http://www.fenicsproject.org https://bitbucket.org/fenics-project/ufc """ # -*- coding: utf-8 -*- __author__ = "Martin Sandve Alnaes, Anders Logg, Kent-Andre Mardal, Ola Skavhaug, and Hans Petter Langtangen" __date__ = "2014-01-07" __version__ = "2.3.0" __license__ = "This code is released into the public domain" UFC_VERSION_MAJOR = 2 UFC_VERSION_MINOR = 3 UFC_VERSION_MAINTENANCE = 0 UFC_VERSION = __version__ from .function import * from .finite_element import * from .dofmap import * from .integrals import * from .form import * from .build import build_ufc_module # Check if we should import development/experimental version #import os #if "UFC_DEV" in os.environ: # from finite_element_1_6 import * # from dofmap_1_6 import * templates = {"function_header": function_header, "function_implementation": function_implementation, "function_combined": function_combined, "finite_element_header": finite_element_header, "finite_element_implementation": finite_element_implementation, "finite_element_combined": finite_element_combined, "dofmap_header": dofmap_header, "dofmap_implementation": dofmap_implementation, "dofmap_combined": dofmap_combined, "cell_integral_header": cell_integral_header, "cell_integral_implementation": cell_integral_implementation, "cell_integral_combined": cell_integral_combined, "exterior_facet_integral_header": exterior_facet_integral_header, "exterior_facet_integral_implementation": exterior_facet_integral_implementation, "exterior_facet_integral_combined": exterior_facet_integral_combined, "interior_facet_integral_header": interior_facet_integral_header, "interior_facet_integral_implementation": interior_facet_integral_implementation, "interior_facet_integral_combined": interior_facet_integral_combined, "point_integral_header": point_integral_header, "point_integral_implementation": point_integral_implementation, "point_integral_combined": point_integral_combined, "form_header": form_header, "form_implementation": form_implementation, "form_combined": form_combined} ufc-2.3.0/src/utils/python/ufc_utils/build.py000066400000000000000000000074061226277264200212300ustar00rootroot00000000000000__author__ = "Johan Hake (hake@simula.no)" __date__ = "2009-03-06 -- 2013-09-12" __license__ = "This code is released into the public domain" __all__ = ['build_ufc_module'] # Modified by Martin Alnes, 2009 import instant import os, sys, re, glob from distutils import sysconfig def build_ufc_module(h_files, source_directory="", system_headers=None, \ **kwargs): """Build a python extension module from ufc compliant source code. The compiled module will be imported and returned by the function. @param h_files: The name(s) of the header files that should be compiled and included in the python extension module. @param source_directory: The directory where the source files reside. @param system_headers: Extra headers that will be #included in the generated wrapper file. Any additional keyword arguments are passed on to instant.build_module. """ # Check h_files argument if isinstance(h_files, str): h_files = [h_files] assert isinstance(h_files, list) , "Provide a 'list' or a 'str' as 'h_files'." assert all(isinstance(f, str) for f in h_files), \ "Elements of 'h_files' must be 'str'." h_files2 = [os.path.join(source_directory, fn) for fn in h_files] for f in h_files2: if not os.path.isfile(f): raise IOError("The file '%s' does not exist." % f) # Check system_headers argument system_headers = system_headers or [] assert isinstance(system_headers, list), "Provide a 'list' as 'system_headers'" assert all(isinstance(header, str) for header in system_headers), \ "Elements of 'system_headers' must be 'str'." system_headers.append("boost/shared_ptr.hpp") # Get the swig interface file declarations declarations = extract_declarations(h_files2) declarations += """ // SWIG version %inline %{ int get_swigversion() { return SWIGVERSION; } %} %pythoncode %{ tmp = hex(get_swigversion()) swigversion = "%d.%d.%d"%(tuple(map(int, [tmp[-5], tmp[-3], tmp[-2:]]))) del tmp, get_swigversion %} """ # Call instant and return module return instant.build_module(wrap_headers = h_files, source_directory = source_directory, additional_declarations = declarations, system_headers = system_headers, cmake_packages = ["UFC"], **kwargs) def extract_declarations(h_files): "Extract information for shared_ptr" # Swig declarations declarations =r""" //Uncomment these to produce code for std::tr1::shared_ptr //#define SWIG_SHARED_PTR_NAMESPACE std //#define SWIG_SHARED_PTR_SUBNAMESPACE tr1 %include // Declare which classes should be stored using shared_ptr %shared_ptr(ufc::cell_integral) %shared_ptr(ufc::dofmap) %shared_ptr(ufc::finite_element) %shared_ptr(ufc::function) %shared_ptr(ufc::form) %shared_ptr(ufc::exterior_facet_integral) %shared_ptr(ufc::interior_facet_integral) %shared_ptr(ufc::point_integral) // Import types from ufc %import(module="ufc") "ufc.h" // Swig shared_ptr macro declarations """ for h_file in h_files: # Read the code code = open(h_file).read() # Extract the class names derived_classes = re.findall(r"class[ ]+([\w]+)[ ]*: public", code) ufc_classes = re.findall(r"public[ ]+(ufc::[\w]+).*", code) ufc_proxy_classes = [s.replace("ufc::", "") for s in ufc_classes] new_share_ptr_format = "%%shared_ptr(%s)" # Write shared_ptr code for swig 2.0.0 or higher declarations += "\n".join(new_share_ptr_format%c for c in derived_classes) declarations += "\n" return declarations ufc-2.3.0/src/utils/python/ufc_utils/dofmap.py000066400000000000000000000204251226277264200213730ustar00rootroot00000000000000# Code generation format strings for UFC (Unified Form-assembly Code) v. 2.3.0. # This code is released into the public domain. # # The FEniCS Project (http://www.fenicsproject.org/) 2006-2014. dofmap_combined = """\ /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class %(classname)s: public ufc::dofmap {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s) : ufc::dofmap()%(initializer_list)s { %(constructor)s } /// Destructor virtual ~%(classname)s() { %(destructor)s } /// Return a string identifying the dofmap virtual const char* signature() const { %(signature)s } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(std::size_t d) const { %(needs_mesh_entities)s } /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const { %(topological_dimension)s } /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const { %(geometric_dimension)s } /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_entities) const { %(global_dimension)s } /// Return the dimension of the local finite element function space for a cell virtual std::size_t local_dimension() const { %(local_dimension)s } /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const { %(num_facet_dofs)s } /// Return the number of dofs associated with each cell entity of dimension d virtual std::size_t num_entity_dofs(std::size_t d) const { %(num_entity_dofs)s } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const ufc::cell& c) const { %(tabulate_dofs)s } /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(std::size_t* dofs, std::size_t facet) const { %(tabulate_facet_dofs)s } /// Tabulate the local-to-local mapping of dofs on entity (d, i) virtual void tabulate_entity_dofs(std::size_t* dofs, std::size_t d, std::size_t i) const { %(tabulate_entity_dofs)s } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double** dof_coordinates, const double* vertex_coordinates) const { %(tabulate_coordinates)s } /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const { %(num_sub_dofmaps)s } /// Create a new dofmap for sub dofmap i (for a mixed element) virtual ufc::dofmap* create_sub_dofmap(std::size_t i) const { %(create_sub_dofmap)s } /// Create a new class instance virtual ufc::dofmap* create() const { %(create)s } }; """ dofmap_header = """\ /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class %(classname)s: public ufc::dofmap {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s); /// Destructor virtual ~%(classname)s(); /// Return a string identifying the dofmap virtual const char* signature() const; /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(std::size_t d) const; /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const; /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const; /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_entities) const; /// Return the dimension of the local finite element function space for a cell virtual std::size_t local_dimension() const; /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const; /// Return the number of dofs associated with each cell entity of dimension d virtual std::size_t num_entity_dofs(std::size_t d) const; /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const ufc::cell& c) const; /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(std::size_t* dofs, std::size_t facet) const; /// Tabulate the local-to-local mapping of dofs on entity (d, i) virtual void tabulate_entity_dofs(std::size_t* dofs, std::size_t d, std::size_t i) const; /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double** coordinates, const double* vertex_coordinates) const; /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const; /// Create a new dofmap for sub dofmap i (for a mixed element) virtual ufc::dofmap* create_sub_dofmap(std::size_t i) const; /// Create a new class instance virtual ufc::dofmap* create() const; }; """ dofmap_implementation = """\ /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::dofmap()%(initializer_list)s { %(constructor)s } /// Destructor %(classname)s::~%(classname)s() { %(destructor)s } /// Return a string identifying the dofmap const char* %(classname)s::signature() const { %(signature)s } /// Return true iff mesh entities of topological dimension d are needed bool %(classname)s::needs_mesh_entities(std::size_t d) const { %(needs_mesh_entities)s } /// Return the topological dimension of the associated cell shape std::size_t %(classname)s::topological_dimension() const { %(topological_dimension)s } /// Return the geometric dimension of the associated cell shape std::size_t %(classname)s::geometric_dimension() const { %(geometric_dimension)s } /// Return the dimension of the global finite element function space std::size_t %(classname)s::global_dimension(const std::vector& num_global_entities) const { %(global_dimension)s } /// Return the dimension of the local finite element function space for a cell std::size_t %(classname)s::local_dimension() const { %(local_dimension)s } /// Return the number of dofs on each cell facet std::size_t %(classname)s::num_facet_dofs() const { %(num_facet_dofs)s } /// Return the number of dofs associated with each cell entity of dimension d std::size_t %(classname)s::num_entity_dofs(std::size_t d) const { %(num_entity_dofs)s } /// Tabulate the local-to-global mapping of dofs on a cell void %(classname)s::tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const ufc::cell& c) const { %(tabulate_dofs)s } /// Tabulate the local-to-local mapping from facet dofs to cell dofs void %(classname)s::tabulate_facet_dofs(std::size_t* dofs, std::size_t facet) const { %(tabulate_facet_dofs)s } /// Tabulate the local-to-local mapping of dofs on entity (d, i) void %(classname)s::tabulate_entity_dofs(std::size_t* dofs, std::size_t d, std::size_t i) const { %(tabulate_entity_dofs)s } /// Tabulate the coordinates of all dofs on a cell void %(classname)s::tabulate_coordinates(double** dof_coordinates, const double* vertex_coordinates) const { %(tabulate_coordinates)s } /// Return the number of sub dofmaps (for a mixed element) std::size_t %(classname)s::num_sub_dofmaps() const { %(num_sub_dofmaps)s } /// Create a new dofmap for sub dofmap i (for a mixed element) ufc::dofmap* %(classname)s::create_sub_dofmap(std::size_t i) const { %(create_sub_dofmap)s } /// Create a new class instance ufc::dofmap* %(classname)s::create() const { %(create)s } """ ufc-2.3.0/src/utils/python/ufc_utils/finite_element.py000066400000000000000000000343251226277264200231200ustar00rootroot00000000000000# Code generation format strings for UFC (Unified Form-assembly Code) v. 2.3.0. # This code is released into the public domain. # # The FEniCS Project (http://www.fenicsproject.org/) 2006-2014. finite_element_combined = """\ /// This class defines the interface for a finite element. class %(classname)s: public ufc::finite_element {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s) : ufc::finite_element()%(initializer_list)s { %(constructor)s } /// Destructor virtual ~%(classname)s() { %(destructor)s } /// Return a string identifying the finite element virtual const char* signature() const { %(signature)s } /// Return the cell shape virtual ufc::shape cell_shape() const { %(cell_shape)s } /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const { %(topological_dimension)s } /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const { %(geometric_dimension)s } /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const { %(space_dimension)s } /// Return the rank of the value space virtual std::size_t value_rank() const { %(value_rank)s } /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const { %(value_dimension)s } /// Evaluate basis function i at given point x in cell virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { %(evaluate_basis)s } /// Evaluate all basis functions at given point x in cell virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { %(evaluate_basis_all)s } /// Evaluate order n derivatives of basis function i at given point x in cell virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { %(evaluate_basis_derivatives)s } /// Evaluate order n derivatives of all basis functions at given point x in cell virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { %(evaluate_basis_derivatives_all)s } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { %(evaluate_dof)s } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { %(evaluate_dofs)s } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { %(interpolate_vertex_values)s } /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const { %(map_from_reference_cell)s } /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const { %(map_to_reference_cell)s } /// Return the number of sub elements (for a mixed element) virtual std::size_t num_sub_elements() const { %(num_sub_elements)s } /// Create a new finite element for sub element i (for a mixed element) virtual ufc::finite_element* create_sub_element(std::size_t i) const { %(create_sub_element)s } /// Create a new class instance virtual ufc::finite_element* create() const { %(create)s } }; """ finite_element_header = """\ /// This class defines the interface for a finite element. class %(classname)s: public ufc::finite_element {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s); /// Destructor virtual ~%(classname)s(); /// Return a string identifying the finite element virtual const char* signature() const; /// Return the cell shape virtual ufc::shape cell_shape() const; /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const; /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const; /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const; /// Return the rank of the value space virtual std::size_t value_rank() const; /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const; /// Evaluate basis function i at given point x in cell virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const; /// Evaluate all basis functions at given point x in cell virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const; /// Evaluate order n derivatives of basis function i at given point x in cell virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const; /// Evaluate order n derivatives of all basis functions at given point x in cell virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const; /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const; /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const; /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const; /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const; /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const; /// Return the number of sub elements (for a mixed element) virtual std::size_t num_sub_elements() const; /// Create a new finite element for sub element i (for a mixed element) virtual ufc::finite_element* create_sub_element(std::size_t i) const; /// Create a new class instance virtual ufc::finite_element* create() const; }; """ finite_element_implementation= """\ /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::finite_element()%(initializer_list)s { %(constructor)s } /// Destructor %(classname)s::~%(classname)s() { %(destructor)s } /// Return a string identifying the finite element const char* %(classname)s::signature() const { %(signature)s } /// Return the cell shape ufc::shape %(classname)s::cell_shape() const { %(cell_shape)s } /// Return the topological dimension of the cell shape std::size_t %(classname)s::topological_dimension() const { %(topological_dimension)s } /// Return the geometric dimension of the cell shape std::size_t %(classname)s::geometric_dimension() const { %(geometric_dimension)s } /// Return the dimension of the finite element function space std::size_t %(classname)s::space_dimension() const { %(space_dimension)s } /// Return the rank of the value space std::size_t %(classname)s::value_rank() const { %(value_rank)s } /// Return the dimension of the value space for axis i std::size_t %(classname)s::value_dimension(std::size_t i) const { %(value_dimension)s } /// Evaluate basis function i at given point x in cell void %(classname)s::evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { %(evaluate_basis)s } /// Evaluate all basis functions at given point x in cell void %(classname)s::evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { %(evaluate_basis_all)s } /// Evaluate order n derivatives of basis function i at given point x in cell void %(classname)s::evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { %(evaluate_basis_derivatives)s } /// Evaluate order n derivatives of all basis functions at given point x in cell void %(classname)s::evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { %(evaluate_basis_derivatives_all)s } /// Evaluate linear functional for dof i on the function f double %(classname)s::evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { %(evaluate_dof)s } /// Evaluate linear functionals for all dofs on the function f void %(classname)s::evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { %(evaluate_dofs)s } /// Interpolate vertex values from dof values void %(classname)s::interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { %(interpolate_vertex_values)s } /// Map coordinate xhat from reference cell to coordinate x in cell void %(classname)s::map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const { %(map_from_reference_cell)s } /// Map from coordinate x in cell to coordinate xhat in reference cell void %(classname)s::map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const { %(map_to_reference_cell)s } /// Return the number of sub elements (for a mixed element) std::size_t %(classname)s::num_sub_elements() const { %(num_sub_elements)s } /// Create a new finite element for sub element i (for a mixed element) ufc::finite_element* %(classname)s::create_sub_element(std::size_t i) const { %(create_sub_element)s } /// Create a new class instance ufc::finite_element* %(classname)s::create() const { %(create)s } """ ufc-2.3.0/src/utils/python/ufc_utils/form.py000066400000000000000000000247111226277264200210720ustar00rootroot00000000000000# Code generation format strings for UFC (Unified Form-assembly Code) v. 2.3.0. # This code is released into the public domain. # # The FEniCS Project (http://www.fenicsproject.org/) 2006-2014. form_combined = """\ /// This class defines the interface for the assembly of the global /// tensor corresponding to a form with r + n arguments, that is, a /// mapping /// /// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R /// /// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r /// global tensor A is defined by /// /// A = a(V1, V2, ..., Vr, w1, w2, ..., wn), /// /// where each argument Vj represents the application to the /// sequence of basis functions of Vj and w1, w2, ..., wn are given /// fixed functions (coefficients). class %(classname)s: public ufc::form {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s) : ufc::form()%(initializer_list)s { %(constructor)s } /// Destructor virtual ~%(classname)s() { %(destructor)s } /// Return a string identifying the form virtual const char* signature() const { %(signature)s } /// Return the rank of the global tensor (r) virtual std::size_t rank() const { %(rank)s } /// Return the number of coefficients (n) virtual std::size_t num_coefficients() const { %(num_coefficients)s } /// Return the number of cell domains virtual std::size_t num_cell_domains() const { %(num_cell_domains)s } /// Return the number of exterior facet domains virtual std::size_t num_exterior_facet_domains() const { %(num_exterior_facet_domains)s } /// Return the number of interior facet domains virtual std::size_t num_interior_facet_domains() const { %(num_interior_facet_domains)s } /// Return the number of point domains virtual std::size_t num_point_domains() const { %(num_point_domains)s } /// Return whether the form has any cell integrals virtual bool has_cell_integrals() const { %(has_cell_integrals)s } /// Return whether the form has any exterior facet integrals virtual bool has_exterior_facet_integrals() const { %(has_exterior_facet_integrals)s } /// Return whether the form has any interior facet integrals virtual bool has_interior_facet_integrals() const { %(has_interior_facet_integrals)s } /// Return whether the form has any point integrals virtual bool has_point_integrals() const { %(has_point_integrals)s } /// Create a new finite element for argument function i virtual ufc::finite_element* create_finite_element(std::size_t i) const { %(create_finite_element)s } /// Create a new dofmap for argument function i virtual ufc::dofmap* create_dofmap(std::size_t i) const { %(create_dofmap)s } /// Create a new cell integral on sub domain i virtual ufc::cell_integral* create_cell_integral(std::size_t i) const { %(create_cell_integral)s } /// Create a new exterior facet integral on sub domain i virtual ufc::exterior_facet_integral* create_exterior_facet_integral(std::size_t i) const { %(create_exterior_facet_integral)s } /// Create a new interior facet integral on sub domain i virtual ufc::interior_facet_integral* create_interior_facet_integral(std::size_t i) const { %(create_interior_facet_integral)s } /// Create a new point integral on sub domain i virtual ufc::point_integral* create_point_integral(std::size_t i) const { %(create_point_integral)s } /// Create a new cell integral on everywhere else virtual ufc::cell_integral* create_default_cell_integral() const { %(create_default_cell_integral)s } /// Create a new exterior facet integral on everywhere else virtual ufc::exterior_facet_integral* create_default_exterior_facet_integral() const { %(create_default_exterior_facet_integral)s } /// Create a new interior facet integral on everywhere else virtual ufc::interior_facet_integral* create_default_interior_facet_integral() const { %(create_default_interior_facet_integral)s } /// Create a new point integral on everywhere else virtual ufc::point_integral* create_default_point_integral() const { %(create_default_point_integral)s } }; """ form_header = """\ /// This class defines the interface for the assembly of the global /// tensor corresponding to a form with r + n arguments, that is, a /// mapping /// /// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R /// /// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r /// global tensor A is defined by /// /// A = a(V1, V2, ..., Vr, w1, w2, ..., wn), /// /// where each argument Vj represents the application to the /// sequence of basis functions of Vj and w1, w2, ..., wn are given /// fixed functions (coefficients). class %(classname)s: public ufc::form {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s); /// Destructor virtual ~%(classname)s(); /// Return a string identifying the form virtual const char* signature() const; /// Return the rank of the global tensor (r) virtual std::size_t rank() const; /// Return the number of coefficients (n) virtual std::size_t num_coefficients() const; /// Return the number of cell domains virtual std::size_t num_cell_domains() const; /// Return the number of exterior facet domains virtual std::size_t num_exterior_facet_domains() const; /// Return the number of interior facet domains virtual std::size_t num_interior_facet_domains() const; /// Return the number of point domains virtual std::size_t num_point_domains() const; /// Return whether the form has any cell integrals virtual bool has_cell_integrals() const; /// Return whether the form has any exterior facet integrals virtual bool has_exterior_facet_integrals() const; /// Return whether the form has any interior facet integrals virtual bool has_interior_facet_integrals() const; /// Return whether the form has any point integrals virtual bool has_point_integrals() const; /// Create a new finite element for argument function i virtual ufc::finite_element* create_finite_element(std::size_t i) const; /// Create a new dofmap for argument function i virtual ufc::dofmap* create_dofmap(std::size_t i) const; /// Create a new cell integral on sub domain i virtual ufc::cell_integral* create_cell_integral(std::size_t i) const; /// Create a new exterior facet integral on sub domain i virtual ufc::exterior_facet_integral* create_exterior_facet_integral(std::size_t i) const; /// Create a new interior facet integral on sub domain i virtual ufc::interior_facet_integral* create_interior_facet_integral(std::size_t i) const; /// Create a new point integral on sub domain i virtual ufc::point_integral* create_point_integral(std::size_t i) const; /// Create a new cell integral on everywhere else virtual ufc::cell_integral* create_default_cell_integral() const; /// Create a new exterior facet integral on everywhere else virtual ufc::exterior_facet_integral* create_default_exterior_facet_integral() const; /// Create a new interior facet integral on everywhere else virtual ufc::interior_facet_integral* create_default_interior_facet_integral() const; /// Create a new point integral on everywhere else virtual ufc::point_integral* create_default_point_integral() const; }; """ form_implementation = """\ /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::form()%(initializer_list)s { %(constructor)s } /// Destructor %(classname)s::~%(classname)s() { %(destructor)s } /// Return a string identifying the form const char* %(classname)s::signature() const { %(signature)s } /// Return the rank of the global tensor (r) std::size_t %(classname)s::rank() const { %(rank)s } /// Return the number of coefficients (n) std::size_t %(classname)s::num_coefficients() const { %(num_coefficients)s } /// Return the number of cell domains std::size_t %(classname)s::num_cell_domains() const { %(num_cell_domains)s } /// Return the number of exterior facet domains std::size_t %(classname)s::num_exterior_facet_domains() const { %(num_exterior_facet_domains)s } /// Return the number of interior facet domains std::size_t %(classname)s::num_interior_facet_domains() const { %(num_interior_facet_domains)s } /// Return the number of point domains std::size_t %(classname)s::num_point_domains() const { %(num_point_domains)s } /// Return whether the form has any cell integrals bool %(classname)s::has_cell_integrals() const { %(has_cell_integrals)s } /// Return whether the form has any exterior facet integrals bool %(classname)s::has_exterior_facet_integrals() const { %(has_exterior_facet_integrals)s } /// Return whether the form has any interior facet integrals bool %(classname)s::has_interior_facet_integrals() const { %(has_interior_facet_integrals)s } /// Return whether the form has any point integrals bool %(classname)s::has_point_integrals() const { %(has_point_integrals)s } /// Create a new finite element for argument function i ufc::finite_element* %(classname)s::create_finite_element(std::size_t i) const { %(create_finite_element)s } /// Create a new dofmap for argument function i ufc::dofmap* %(classname)s::create_dofmap(std::size_t i) const { %(create_dofmap)s } /// Create a new cell integral on sub domain i ufc::cell_integral* %(classname)s::create_cell_integral(std::size_t i) const { %(create_cell_integral)s } /// Create a new exterior facet integral on sub domain i ufc::exterior_facet_integral* %(classname)s::create_exterior_facet_integral(std::size_t i) const { %(create_exterior_facet_integral)s } /// Create a new interior facet integral on sub domain i ufc::interior_facet_integral* %(classname)s::create_interior_facet_integral(std::size_t i) const { %(create_interior_facet_integral)s } /// Create a new point integral on sub domain i ufc::point_integral* %(classname)s::create_point_integral(std::size_t i) const { %(create_point_integral)s } /// Create a new cell integral on everywhere else ufc::cell_integral* %(classname)s::create_default_cell_integral() const { %(create_default_cell_integral)s } /// Create a new exterior facet integral on everywhere else ufc::exterior_facet_integral* %(classname)s::create_default_exterior_facet_integral() const { %(create_default_exterior_facet_integral)s } /// Create a new interior facet integral on everywhere else ufc::interior_facet_integral* %(classname)s::create_default_interior_facet_integral() const { %(create_default_interior_facet_integral)s } /// Create a new point integral on everywhere else ufc::point_integral* %(classname)s::create_default_point_integral() const { %(create_default_point_integral)s } """ ufc-2.3.0/src/utils/python/ufc_utils/function.py000066400000000000000000000032511226277264200217500ustar00rootroot00000000000000# Code generation format strings for UFC (Unified Form-assembly Code) v. 2.3.0. # This code is released into the public domain. # # The FEniCS Project (http://www.fenicsproject.org/) 2006-2014 function_combined = """\ /// This class defines the interface for a general tensor-valued function. class %(classname)s: public ufc::function {%(members)s public: /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::function()%(initializer_list)s { %(constructor)s } /// Destructor virtual ~%(classname)s() { %(destructor)s } /// Evaluate function at given point in cell virtual void evaluate(double* values, const double* coordinates, const ufc::cell& c) const { %(evaluate)s } }; """ function_header = """\ /// This class defines the interface for a general tensor-valued function. class %(classname)s: public ufc::function {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s); /// Destructor virtual ~%(classname)s(); /// Evaluate function at given point in cell virtual void evaluate(double* values, const double* coordinates, const ufc::cell& c) const; }; """ function_implementation = """\ /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::function()%(initializer_list)s { %(constructor)s } /// Destructor %(classname)s::~%(classname)s() { %(destructor)s } /// Evaluate function at given point in cell void %(classname)s::evaluate(double* values, const double* coordinates, const ufc::cell& c) const { %(evaluate)s } """ ufc-2.3.0/src/utils/python/ufc_utils/integrals.py000066400000000000000000000222241226277264200221140ustar00rootroot00000000000000# Code generation format strings for UFC (Unified Form-assembly Code) v. 2.3.0. # This code is released into the public domain. # # The FEniCS Project (http://www.fenicsproject.org/) 2006-2014 cell_integral_combined = """\ /// This class defines the interface for the tabulation of the cell /// tensor corresponding to the local contribution to a form from /// the integral over a cell. class %(classname)s: public ufc::cell_integral {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s) : ufc::cell_integral()%(initializer_list)s { %(constructor)s } /// Destructor virtual ~%(classname)s() { %(destructor)s } /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, int cell_orientation) const { %(tabulate_tensor)s } }; """ cell_integral_header = """\ /// This class defines the interface for the tabulation of the cell /// tensor corresponding to the local contribution to a form from /// the integral over a cell. class %(classname)s: public ufc::cell_integral {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s); /// Destructor virtual ~%(classname)s(); /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, int cell_orientation) const; }; """ cell_integral_implementation = """\ /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::cell_integral()%(initializer_list)s { %(constructor)s } /// Destructor %(classname)s::~%(classname)s() { %(destructor)s } /// Tabulate the tensor for the contribution from a local cell void %(classname)s::tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, int cell_orientation) const { %(tabulate_tensor)s } """ exterior_facet_integral_combined = """\ /// This class defines the interface for the tabulation of the /// exterior facet tensor corresponding to the local contribution to /// a form from the integral over an exterior facet. class %(classname)s: public ufc::exterior_facet_integral {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s) : ufc::exterior_facet_integral()%(initializer_list)s { %(constructor)s } /// Destructor virtual ~%(classname)s() { %(destructor)s } /// Tabulate the tensor for the contribution from a local exterior facet virtual void tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, std::size_t facet) const { %(tabulate_tensor)s } }; """ exterior_facet_integral_header = """\ /// This class defines the interface for the tabulation of the /// exterior facet tensor corresponding to the local contribution to /// a form from the integral over an exterior facet. class %(classname)s: public ufc::exterior_facet_integral {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s); /// Destructor virtual ~%(classname)s(); /// Tabulate the tensor for the contribution from a local exterior facet virtual void tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, std::size_t facet) const; }; """ exterior_facet_integral_implementation = """\ /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::exterior_facet_integral()%(initializer_list)s { %(constructor)s } /// Destructor %(classname)s::~%(classname)s() { %(destructor)s } /// Tabulate the tensor for the contribution from a local exterior facet void %(classname)s::tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, std::size_t facet) const { %(tabulate_tensor)s } """ interior_facet_integral_combined = """\ /// This class defines the interface for the tabulation of the /// interior facet tensor corresponding to the local contribution to /// a form from the integral over an interior facet. class %(classname)s: public ufc::interior_facet_integral {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s) : ufc::interior_facet_integral()%(initializer_list)s { %(constructor)s } /// Destructor virtual ~%(classname)s() { %(destructor)s } /// Tabulate the tensor for the contribution from a local interior facet virtual void tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates_0, const double* %(restrict)s vertex_coordinates_1, std::size_t facet_0, std::size_t facet_1) const { %(tabulate_tensor)s } }; """ interior_facet_integral_header = """\ /// This class defines the interface for the tabulation of the /// interior facet tensor corresponding to the local contribution to /// a form from the integral over an interior facet. class %(classname)s: public ufc::interior_facet_integral {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s); /// Destructor virtual ~%(classname)s(); /// Tabulate the tensor for the contribution from a local interior facet virtual void tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates_0, const double* %(restrict)s vertex_coordinates_1, std::size_t facet_0, std::size_t facet_1) const; }; """ interior_facet_integral_implementation = """\ /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::interior_facet_integral()%(initializer_list)s { %(constructor)s } /// Destructor %(classname)s::~%(classname)s() { %(destructor)s } /// Tabulate the tensor for the contribution from a local interior facet void %(classname)s::tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates_0, const double* %(restrict)s vertex_coordinates_1, std::size_t facet_0, std::size_t facet_1) const { %(tabulate_tensor)s } """ point_integral_combined = """\ /// This class defines the interface for the tabulation of /// an expression evaluated at exactly one point. class %(classname)s: public ufc::point_integral {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s) : ufc::point_integral()%(initializer_list)s { %(constructor)s } /// Destructor virtual ~%(classname)s() { %(destructor)s } /// Tabulate the tensor for the contribution from the local vertex virtual void tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, std::size_t vertex) const { %(tabulate_tensor)s } }; """ point_integral_header = """\ /// This class defines the interface for the tabulation of /// an expression evaluated at exactly one point. class %(classname)s: public ufc::point_integral {%(members)s public: /// Constructor %(classname)s(%(constructor_arguments)s); /// Destructor virtual ~%(classname)s(); /// Tabulate the tensor for the contribution from the local vertex virtual void tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, std::size_t vertex) const; }; """ point_integral_implementation = """\ /// Constructor %(classname)s::%(classname)s(%(constructor_arguments)s) : ufc::point_integral()%(initializer_list)s { %(constructor)s } /// Destructor %(classname)s::~%(classname)s() { %(destructor)s } /// Tabulate the tensor for the contribution from the local vertex void %(classname)s::tabulate_tensor(double* %(restrict)s A, const double * const * %(restrict)s w, const double* %(restrict)s vertex_coordinates, std::size_t vertex) const { %(tabulate_tensor)s } """