Skip to content

Commit

Permalink
CrouzeixRaviart: integral variant
Browse files Browse the repository at this point in the history
  • Loading branch information
pbrubeck committed Dec 11, 2024
1 parent 11dc133 commit 10a4f98
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 32 deletions.
40 changes: 28 additions & 12 deletions FIAT/crouzeix_raviart.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
#
# Last changed: 2010-01-28

import numpy
from FIAT import finite_element, polynomial_set, dual_set, functional
from FIAT.check_format_variant import check_format_variant
from FIAT.quadrature_schemes import create_quadrature
from FIAT.quadrature import FacetQuadratureRule


def _initialize_entity_ids(topology):
Expand All @@ -25,25 +29,35 @@ class CrouzeixRaviartDualSet(dual_set.DualSet):
"""Dual basis for Crouzeix-Raviart element (linears continuous at
boundary midpoints)."""

def __init__(self, cell, degree):
def __init__(self, cell, degree, variant, interpolant_deg):

# Get topology dictionary
d = cell.get_spatial_dimension()
topology = cell.get_topology()

# Initialize empty nodes and entity_ids
entity_ids = _initialize_entity_ids(topology)
nodes = [None for i in list(topology[d - 1].keys())]
nodes = []

# Construct nodes and entity_ids
for i in topology[d - 1]:

# Construct midpoint
x = cell.make_points(d - 1, i, d)[0]

# Degree of freedom number i is evaluation at midpoint
nodes[i] = functional.PointEvaluation(cell, x)
entity_ids[d - 1][i] += [i]
if variant == "point":
for i in sorted(topology[d - 1]):
# Construct midpoint
pt, = cell.make_points(d - 1, i, d)
# Degree of freedom number i is evaluation at midpoint
nodes.append(functional.PointEvaluation(cell, pt))
entity_ids[d - 1][i].append(i)
else:
facet = cell.construct_subelement(d-1)
Q_facet = create_quadrature(facet, degree + interpolant_deg)
for i in sorted(topology[d - 1]):
# Map quadrature
Q = FacetQuadratureRule(cell, d-1, i, Q_facet)
f = 1 / Q.jacobian_determinant()
f_at_qpts = numpy.full(Q.get_weights().shape, f)
# Degree of freedom number i is integral moment on facet
nodes.append(functional.IntegralMoment(cell, Q, f_at_qpts))
entity_ids[d - 1][i].append(i)

# Initialize super-class
super().__init__(nodes, cell, entity_ids)
Expand All @@ -57,7 +71,9 @@ class CrouzeixRaviart(finite_element.CiarletElement):
Dual basis: Evaluation at facet midpoints
"""

def __init__(self, cell, degree):
def __init__(self, cell, degree, variant=None):

variant, interpolant_deg = check_format_variant(variant, degree)

# Crouzeix Raviart is only defined for polynomial degree == 1
if not (degree == 1):
Expand All @@ -66,5 +82,5 @@ def __init__(self, cell, degree):
# Construct polynomial spaces, dual basis and initialize
# FiniteElement
space = polynomial_set.ONPolynomialSet(cell, 1)
dual = CrouzeixRaviartDualSet(cell, 1)
dual = CrouzeixRaviartDualSet(cell, 1, variant, interpolant_deg)
super().__init__(space, dual, 1)
20 changes: 1 addition & 19 deletions gem/utils.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
import collections


# This is copied from PyOP2, and it is here to be available for both
# FInAT and TSFC without depending on PyOP2.
class cached_property(object):
"""A read-only @property that is only evaluated once. The value is cached
on the object itself rather than the function or class; this should prevent
memory leakage."""
def __init__(self, fget, doc=None):
self.fget = fget
self.__doc__ = doc or fget.__doc__
self.__name__ = fget.__name__
self.__module__ = fget.__module__

def __get__(self, obj, cls):
if obj is None:
return self
obj.__dict__[self.__name__] = result = self.fget(obj)
return result
from functools import cached_property


def groupby(iterable, key=None):
Expand Down
2 changes: 1 addition & 1 deletion test/FIAT/regression/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def create_data(family, dim, degree):
'''Create the reference data.
'''
kwargs = {}
if family in {"Regge", "Hellan-Herrmann-Johnson"}:
if family in {"Crouzeix-Raviart", "Regge", "Hellan-Herrmann-Johnson"}:
kwargs["variant"] = "point"
# Get domain and element class
domain = ufc_simplex(dim)
Expand Down

0 comments on commit 10a4f98

Please sign in to comment.