# -*- coding: utf-8 -*-
"""Code generation format strings for UFC (Unified Form-assembly Code)
Five format strings are defined for each of the following UFC classes:
cell_integral
exterior_facet_integral
interior_facet_integral
custom_integral
cutcell_integral
interface_integral
overlap_integral
function
finite_element
dofmap
coordinate_mapping
form
The strings are named:
'<classname>_header'
'<classname>_implementation'
'<classname>_combined'
'<classname>_jit_header'
'<classname>_jit_implementation'
The header and implementation contain the definition and declaration
of the class 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.
The _jit_ versions are used in the jit compiler and contains some additional
factory functions exported as extern "C" to allow construction of compiled
objects through ctypes without dealing with C++ ABI and name mangling issues.
Each string has at least 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/ffc
"""
__author__ = "Martin Sandve Alnæs, Anders Logg, Kent-Andre Mardal, Ola Skavhaug, and Hans Petter Langtangen"
__date__ = "2017-05-09"
__version__ = "2018.1.0"
__license__ = "This code is released into the public domain"
import os
from hashlib import sha1
from ffc.backends.ufc.function import *
from ffc.backends.ufc.finite_element import *
from ffc.backends.ufc.dofmap import *
from ffc.backends.ufc.coordinate_mapping import *
from ffc.backends.ufc.integrals import *
from ffc.backends.ufc.form import *
# Get abspath on import, it can in some cases be
# a relative path w.r.t. curdir on startup
_include_path = os.path.dirname(os.path.abspath(__file__))
[docs]def get_include_path():
"Return location of UFC header files"
return _include_path
# Platform specific snippets for controlling visilibity of exported symbols in generated shared libraries
visibility_snippet = """
// Based on https://gcc.gnu.org/wiki/Visibility
#if defined _WIN32 || defined __CYGWIN__
#ifdef __GNUC__
#define DLL_EXPORT __attribute__ ((dllexport))
#else
#define DLL_EXPORT __declspec(dllexport)
#endif
#else
#define DLL_EXPORT __attribute__ ((visibility ("default")))
#endif
"""
# Generic factory function signature
factory_decl = """
extern "C" %(basename)s * create_%(publicname)s();
"""
# Generic factory function implementation. Set basename to the base class,
# and note that publicname and privatename does not need to match, allowing
# multiple factory functions to return the same object.
factory_impl = """
extern "C" DLL_EXPORT %(basename)s * create_%(publicname)s()
{
return new %(privatename)s();
}
"""
[docs]def all_ufc_classnames():
"Build list of all classnames."
integral_names = ["cell", "exterior_facet", "interior_facet", "vertex", "custom", "cutcell", "interface", "overlap"]
integral_classnames = [integral_name + "_integral" for integral_name in integral_names]
jitable_classnames = ["finite_element", "dofmap", "coordinate_mapping", "form"]
classnames = ["function"] + jitable_classnames + integral_classnames
return classnames
def _build_templates():
"Build collection of all templates to store in the templates dict."
templates = {}
classnames = all_ufc_classnames()
for classname in classnames:
# Expect all classes to have header, implementation, and combined versions
header = globals()[classname + "_header"]
implementation = globals()[classname + "_implementation"]
combined = globals()[classname + "_combined"]
# Construct jit header with class and factory function signature
_fac_decl = factory_decl % {
"basename": "ufc::" + classname,
"publicname": "%(classname)s",
"privatename": "%(classname)s",
}
jit_header = header + _fac_decl
# Construct jit implementation template with class declaration,
# factory function implementation, and class definition
_fac_impl = factory_impl % {
"basename": "ufc::" + classname,
"publicname": "%(classname)s",
"privatename": "%(classname)s",
}
jit_implementation = implementation + _fac_impl
# Store all in templates dict
templates[classname + "_header"] = header
templates[classname + "_implementation"] = implementation
templates[classname + "_combined"] = combined
templates[classname + "_jit_header"] = jit_header
templates[classname + "_jit_implementation"] = jit_implementation
return templates
def _compute_ufc_templates_signature(templates):
# Compute signature of jit templates
h = sha1()
for k in sorted(templates):
h.update(k.encode("utf-8"))
h.update(templates[k].encode("utf-8"))
return h.hexdigest()
def _compute_ufc_signature():
# Compute signature of ufc header files
h = sha1()
for fn in ("ufc.h", "ufc_geometry.h"):
with open(os.path.join(get_include_path(), fn)) as f:
h.update(f.read().encode("utf-8"))
return h.hexdigest()
# Build these on import
templates = _build_templates()
_ufc_signature = _compute_ufc_signature()
_ufc_templates_signature = _compute_ufc_templates_signature(templates)
[docs]def get_ufc_signature():
"""Return SHA-1 hash of the contents of ufc.h and ufc_geometry.h.
In this implementation, the value is computed on import.
"""
return _ufc_signature
[docs]def get_ufc_templates_signature():
"""Return SHA-1 hash of the ufc code templates.
In this implementation, the value is computed on import.
"""
return _ufc_templates_signature
[docs]def get_ufc_cxx_flags():
"""Return C++ flags for compiling UFC C++11 code.
Return type is a list of strings.
Used internally in some tests.
"""
return ["-std=c++11"]
# ufc_signature() already introduced to FFC standard in 1.7.0dev,
# called by the dolfin cmake build system to compare against
# future imported ffc versions for compatibility.
ufc_signature = get_ufc_signature