[fiat] 01/01: New upstream version 2017.2.0.0

Drew Parsons dparsons at moszumanska.debian.org
Fri Jan 19 15:53:29 UTC 2018


This is an automated email from the git hooks/post-receive script.

dparsons pushed a commit to annotated tag upstream/2017.2.0.0
in repository fiat.

commit 64926666e24980325d4f5522de527be37fe3075f
Author: Drew Parsons <dparsons at debian.org>
Date:   Fri Jan 19 23:40:39 2018 +0800

    New upstream version 2017.2.0.0
---
 .circleci/config.yml                     | 20 ++++++++
 FIAT/dual_set.py                         |  1 +
 FIAT/gauss_legendre.py                   |  4 +-
 FIAT/gauss_lobatto_legendre.py           |  4 +-
 FIAT/hdiv_trace.py                       |  4 ++
 FIAT/reference_element.py                | 24 ++++++++++
 README.rst                               |  4 +-
 doc/sphinx/source/releases.rst           |  1 +
 doc/sphinx/source/releases/v2017.2.0.rst |  2 +-
 test/unit/test_fiat.py                   | 78 +++++++++++++++++++++++++++++---
 test/unit/test_reference_element.py      | 48 ++++++++++++++++++++
 11 files changed, 176 insertions(+), 14 deletions(-)

diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..2fffb99
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,20 @@
+version: 2
+jobs:
+  build:
+    docker:
+      - image: circleci/python:3.6
+    working_directory:  ~/fiat-test
+    steps:
+      - checkout
+      - run:
+          name: Install dependencies  # Install with sudo as tests not run as superuser in circleci/python
+          command: sudo pip install flake8 pytest six numpy sympy --upgrade
+      - run:
+          name: Install FIAT
+          command: pip install . --user
+      - run:
+          name: Run flake8 tests
+          command: python -m flake8 .
+      - run:
+          name: Run unit tests
+          command: DATA_REPO_GIT="" python -m pytest -v test/
diff --git a/FIAT/dual_set.py b/FIAT/dual_set.py
index 13b268e..577baad 100644
--- a/FIAT/dual_set.py
+++ b/FIAT/dual_set.py
@@ -37,6 +37,7 @@ class DualSet(object):
 
                 for d, se in sub_entities:
                     ids += self.entity_ids[d][se]
+                ids.sort()
                 self.entity_closure_ids[d][e] = ids
 
     def get_nodes(self):
diff --git a/FIAT/gauss_legendre.py b/FIAT/gauss_legendre.py
index ae0272a..42b39aa 100644
--- a/FIAT/gauss_legendre.py
+++ b/FIAT/gauss_legendre.py
@@ -28,8 +28,8 @@ class GaussLegendreDualSet(dual_set.DualSet):
     def __init__(self, ref_el, degree):
         entity_ids = {0: {0: [], 1: []},
                       1: {0: list(range(0, degree+1))}}
-        l = quadrature.GaussLegendreQuadratureLineRule(ref_el, degree+1)
-        nodes = [functional.PointEvaluation(ref_el, x) for x in l.pts]
+        lr = quadrature.GaussLegendreQuadratureLineRule(ref_el, degree+1)
+        nodes = [functional.PointEvaluation(ref_el, x) for x in lr.pts]
 
         super(GaussLegendreDualSet, self).__init__(nodes, ref_el, entity_ids)
 
diff --git a/FIAT/gauss_lobatto_legendre.py b/FIAT/gauss_lobatto_legendre.py
index ecbe015..b8fd6af 100644
--- a/FIAT/gauss_lobatto_legendre.py
+++ b/FIAT/gauss_lobatto_legendre.py
@@ -29,8 +29,8 @@ class GaussLobattoLegendreDualSet(dual_set.DualSet):
     def __init__(self, ref_el, degree):
         entity_ids = {0: {0: [0], 1: [degree]},
                       1: {0: list(range(1, degree))}}
-        l = quadrature.GaussLobattoLegendreQuadratureLineRule(ref_el, degree+1)
-        nodes = [functional.PointEvaluation(ref_el, x) for x in l.pts]
+        lr = quadrature.GaussLobattoLegendreQuadratureLineRule(ref_el, degree+1)
+        nodes = [functional.PointEvaluation(ref_el, x) for x in lr.pts]
 
         super(GaussLobattoLegendreDualSet, self).__init__(nodes, ref_el, entity_ids)
 
diff --git a/FIAT/hdiv_trace.py b/FIAT/hdiv_trace.py
index a59e051..af5b375 100644
--- a/FIAT/hdiv_trace.py
+++ b/FIAT/hdiv_trace.py
@@ -275,6 +275,10 @@ class HDivTrace(FiniteElement):
         """Return number of members of the expansion set."""
         raise NotImplementedError("get_num_members not implemented for the trace element.")
 
+    @staticmethod
+    def is_nodal():
+        return True
+
 
 def construct_dg_element(ref_el, degree):
     """Constructs a discontinuous galerkin element of a given degree
diff --git a/FIAT/reference_element.py b/FIAT/reference_element.py
index 786c671..412936f 100644
--- a/FIAT/reference_element.py
+++ b/FIAT/reference_element.py
@@ -130,8 +130,24 @@ class Cell(object):
                         if vertices.issuperset(vertices_):
                             sub_entities.append((dim_, e_))
 
+                # Sort for the sake of determinism and by UFC conventions
                 self.sub_entities[dim][e] = sorted(sub_entities)
 
+        # Build connectivity dictionary for easier queries
+        self.connectivity = {}
+        for dim0, sub_entities in iteritems(self.sub_entities):
+
+            # Skip tensor product entities
+            # TODO: Can we do something better?
+            if isinstance(dim0, tuple):
+                continue
+
+            for entity, sub_sub_entities in sorted(iteritems(sub_entities)):
+                for dim1 in range(dim0+1):
+                    d01_entities = filter(lambda x: x[0] == dim1, sub_sub_entities)
+                    d01_entities = tuple(x[1] for x in d01_entities)
+                    self.connectivity.setdefault((dim0, dim1), []).append(d01_entities)
+
     def _key(self):
         """Hashable object key data (excluding type)."""
         # Default: only type matters
@@ -166,6 +182,14 @@ class Cell(object):
         and each value is a dictionary mapping."""
         return self.topology
 
+    def get_connectivity(self):
+        """Returns a dictionary encoding the connectivity of the element.
+
+        The dictionary's keys are the spatial dimensions pairs ((1, 0),
+        (2, 0), (2, 1), ...) and each value is a list with entities
+        of second dimension ordered by local dim0-dim1 numbering."""
+        return self.connectivity
+
     def get_vertices_of_subcomplex(self, t):
         """Returns the tuple of vertex coordinates associated with the labels
         contained in the iterable t."""
diff --git a/README.rst b/README.rst
index 6014d29..9853fd1 100644
--- a/README.rst
+++ b/README.rst
@@ -36,8 +36,8 @@ testing.
    :target: https://bitbucket.org/fenics-project/fiat/addon/pipelines/home
    :alt: Pipelines Build Status
 
-.. image:: http://fenics-bamboo.simula.no:8085/plugins/servlet/wittified/build-status/FIAT-FD
-   :target: http://fenics-bamboo.simula.no:8085/browse/FIAT-FD/latest
+.. image:: http://magpie.bpi.cam.ac.uk:8085/plugins/servlet/wittified/build-status/FIAT-FD
+   :target: http://magpie.bpi.cam.ac.uk:8085/browse/FIAT-FD
    :alt: Bamboo Build Status
 
 
diff --git a/doc/sphinx/source/releases.rst b/doc/sphinx/source/releases.rst
index 4758874..787e2f2 100644
--- a/doc/sphinx/source/releases.rst
+++ b/doc/sphinx/source/releases.rst
@@ -9,6 +9,7 @@ Release notes
    :maxdepth: 2
 
    releases/next
+   releases/v2017.2.0
    releases/v2017.1.0.post1
    releases/v2017.1.0
    releases/v2016.2.0
diff --git a/doc/sphinx/source/releases/v2017.2.0.rst b/doc/sphinx/source/releases/v2017.2.0.rst
index 62eb734..a7111bb 100644
--- a/doc/sphinx/source/releases/v2017.2.0.rst
+++ b/doc/sphinx/source/releases/v2017.2.0.rst
@@ -2,7 +2,7 @@
 Changes in version 2017.2.0
 ===========================
 
-FIAT 2017.2.0 was released on 2017-09-19.
+FIAT 2017.2.0 was released on 2017-11-30.
 
 Summary of changes
 ==================
diff --git a/test/unit/test_fiat.py b/test/unit/test_fiat.py
index 9c53af8..6deac7a 100644
--- a/test/unit/test_fiat.py
+++ b/test/unit/test_fiat.py
@@ -35,7 +35,7 @@ from FIAT.mixed import MixedElement
 from FIAT.nedelec import Nedelec                                # noqa: F401
 from FIAT.nedelec_second_kind import NedelecSecondKind          # noqa: F401
 from FIAT.regge import Regge                                    # noqa: F401
-from FIAT.hdiv_trace import HDivTrace                           # noqa: F401
+from FIAT.hdiv_trace import HDivTrace, map_to_reference_facet   # noqa: F401
 from FIAT.hellan_herrmann_johnson import HellanHerrmannJohnson  # noqa: F401
 from FIAT.brezzi_douglas_fortin_marini import BrezziDouglasFortinMarini  # noqa: F401
 from FIAT.gauss_legendre import GaussLegendre                   # noqa: F401
@@ -52,7 +52,7 @@ from FIAT.enriched import EnrichedElement                       # noqa: F401
 from FIAT.nodal_enriched import NodalEnrichedElement
 
 
-I = UFCInterval()
+I = UFCInterval()  # noqa: E741
 T = UFCTriangle()
 S = UFCTetrahedron()
 
@@ -226,6 +226,14 @@ elements = [
                "Hcurl(TensorProductElement(DiscontinuousLagrange(I, 0), Lagrange(I, 1)))"
                ")"),
     # Following elements are checked using tabulate
+    xfail_impl("HDivTrace(T, 0)"),
+    xfail_impl("HDivTrace(T, 1)"),
+    xfail_impl("HDivTrace(T, 2)"),
+    xfail_impl("HDivTrace(T, 3)"),
+    xfail_impl("HDivTrace(S, 0)"),
+    xfail_impl("HDivTrace(S, 1)"),
+    xfail_impl("HDivTrace(S, 2)"),
+    xfail_impl("HDivTrace(S, 3)"),
     xfail_impl("TensorProductElement(Lagrange(I, 1), Lagrange(I, 1))"),
     xfail_impl("TensorProductElement(Lagrange(I, 2), Lagrange(I, 2))"),
     xfail_impl("TensorProductElement(TensorProductElement(Lagrange(I, 1), Lagrange(I, 1)), Lagrange(I, 1))"),
@@ -347,24 +355,80 @@ def test_mixed_is_not_nodal():
     "FlattenedDimensions(TensorProductElement(FlattenedDimensions(TensorProductElement(Lagrange(I, 1), Lagrange(I, 1))), Lagrange(I, 1)))",
     "FlattenedDimensions(TensorProductElement(FlattenedDimensions(TensorProductElement(Lagrange(I, 2), Lagrange(I, 2))), Lagrange(I, 2)))",
 ])
-def test_nodality_tpe(element):
-    """Check that generated TensorProductElements are nodal, i.e. nodes evaluated
-    on basis functions give Kronecker delta
+def test_nodality_tabulate(element):
+    """Check that certain elements (which do no implement
+    get_nodal_basis) are nodal too, by tabulating at nodes
+    (assuming nodes are point evaluation)
     """
     # Instantiate element
     element = eval(element)
 
     # Get nodes coordinates
-    nodes_coord = list(next(iter(f.get_point_dict().keys())) for f in element.dual_basis())
+    nodes_coords = []
+    for node in element.dual_basis():
+        # Assume point evaluation
+        (coords, weights), = node.get_point_dict().items()
+        assert weights == [(1.0, ())]
+
+        nodes_coords.append(coords)
 
     # Check nodality
-    for j, x in enumerate(nodes_coord):
+    for j, x in enumerate(nodes_coords):
         table = element.tabulate(0, (x,))
         basis = table[list(table.keys())[0]]
         for i in range(len(basis)):
             assert np.isclose(basis[i], 1.0 if i == j else 0.0)
 
 
+ at pytest.mark.parametrize('element', [
+    "HDivTrace(T, 0)",
+    "HDivTrace(T, 1)",
+    "HDivTrace(T, 2)",
+    "HDivTrace(T, 3)",
+    "HDivTrace(S, 0)",
+    "HDivTrace(S, 1)",
+    "HDivTrace(S, 2)",
+    "HDivTrace(S, 3)",
+])
+def test_facet_nodality_tabulate(element):
+    """Check that certain elements (which do no implement get_nodal_basis)
+    are nodal too, by tabulating facet-wise at nodes (assuming nodes
+    are point evaluation)
+    """
+    # Instantiate element
+    element = eval(element)
+
+    # Dof/Node coordinates and respective facet
+    nodes_coords = []
+
+    # Iterate over facet degrees of freedom
+    entity_dofs = element.dual.entity_ids
+    facet_dim = sorted(entity_dofs.keys())[-2]
+    facet_dofs = entity_dofs[facet_dim]
+    dofs = element.dual_basis()
+    vertices = element.ref_el.vertices
+
+    for (facet, indices) in facet_dofs.items():
+        for i in indices:
+            node = dofs[i]
+            # Assume point evaluation
+            (coords, weights), = node.get_point_dict().items()
+            assert weights == [(1.0, ())]
+
+            # Map dof coordinates to reference element due to
+            # HdivTrace interface peculiarity
+            ref_coords = map_to_reference_facet((coords,), vertices, facet)
+            assert len(ref_coords) == 1
+            nodes_coords.append((facet, ref_coords[0]))
+
+    # Check nodality
+    for j, (facet, x) in enumerate(nodes_coords):
+        table = element.tabulate(0, (x,), entity=(facet_dim, facet))
+        basis = table[list(table.keys())[0]]
+        for i in range(len(basis)):
+            assert np.isclose(basis[i], 1.0 if i == j else 0.0)
+
+
 if __name__ == '__main__':
     import os
     pytest.main(os.path.abspath(__file__))
diff --git a/test/unit/test_reference_element.py b/test/unit/test_reference_element.py
index 56501a2..b9b6b9c 100644
--- a/test/unit/test_reference_element.py
+++ b/test/unit/test_reference_element.py
@@ -19,6 +19,8 @@ from __future__ import absolute_import, print_function, division
 
 import pytest
 import numpy as np
+import six
+from six.moves import range
 
 from FIAT.reference_element import UFCInterval, UFCTriangle, UFCTetrahedron
 from FIAT.reference_element import Point, TensorProductCell, UFCQuadrilateral, UFCHexahedron
@@ -33,6 +35,52 @@ interval_x_interval = TensorProductCell(interval, interval)
 triangle_x_interval = TensorProductCell(triangle, interval)
 quadrilateral_x_interval = TensorProductCell(quadrilateral, interval)
 
+ufc_tetrahedron_21connectivity = [(0, 1, 2), (0, 3, 4), (1, 3, 5), (2, 4, 5)]
+ufc_hexahedron_21connectivity = [(0, 1, 4, 5), (2, 3, 6, 7), (0, 2, 8, 9),
+                                 (1, 3, 10, 11), (4, 6, 8, 10), (5, 7, 9, 11)]
+
+
+ at pytest.mark.parametrize(('cell', 'connectivity'),
+                         [(tetrahedron, ufc_tetrahedron_21connectivity),
+                          (hexahedron, ufc_hexahedron_21connectivity),
+                          pytest.mark.xfail((triangle_x_interval, [])),
+                          pytest.mark.xfail((quadrilateral_x_interval, []))])
+def test_ufc_connectivity_21(cell, connectivity):
+    """Check face-edge connectivity builds what UFC expects.
+    This is only non-trivial case ; the rest is x-0 and D-x,
+    see below."""
+    assert cell.get_connectivity()[(2, 1)] == connectivity
+
+
+ at pytest.mark.parametrize('cell',
+                         [point, interval, triangle, tetrahedron,
+                          quadrilateral, hexahedron,
+                          pytest.mark.xfail(interval_x_interval),
+                          pytest.mark.xfail(triangle_x_interval),
+                          pytest.mark.xfail(quadrilateral_x_interval)])
+def test_ufc_connectivity_x0(cell):
+    """Check x-0 connectivity is just what get_topology gives"""
+    for dim0 in range(cell.get_spatial_dimension()+1):
+        connectivity = cell.get_connectivity()[(dim0, 0)]
+        topology = cell.get_topology()[dim0]
+        assert len(connectivity) == len(topology)
+        assert all(connectivity[i] == t for i, t in six.iteritems(topology))
+
+
+ at pytest.mark.parametrize('cell',
+                         [point, interval, triangle, tetrahedron,
+                          quadrilateral, hexahedron,
+                          pytest.mark.xfail(interval_x_interval),
+                          pytest.mark.xfail(triangle_x_interval),
+                          pytest.mark.xfail(quadrilateral_x_interval)])
+def test_ufc_connectivity_Dx(cell):
+    """Check D-x connectivity is just [(0,1,2,...)]"""
+    D = cell.get_spatial_dimension()
+    for dim1 in range(D+1):
+        connectivity = cell.get_connectivity()[(D, dim1)]
+        assert len(connectivity) == 1
+        assert connectivity[0] == tuple(range(len(connectivity[0])))
+
 
 @pytest.mark.parametrize(('cell', 'volume'),
                          [pytest.mark.xfail((point, 1)),

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/fenics/fiat.git



More information about the debian-science-commits mailing list