-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add fuse element infrastructure #127
base: master
Are you sure you want to change the base?
Changes from 13 commits
6573217
dc5188a
c75efef
dfd1347
21f1bf1
3eb0d1a
2c21e27
2b45bd5
9b05688
3a7bb5b
8d1a074
b72cd61
a89d057
ac81474
9420a6d
be81de3
2e3ed6c
0b593e5
263dad1
3a5b073
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -176,15 +176,51 @@ def polynomial_set_union_normalized(A, B): | |
not contain any of the same members of the set, as we construct a | ||
span via SVD. | ||
""" | ||
new_coeffs = numpy.concatenate((A.coeffs, B.coeffs), axis=0) | ||
assert A.get_reference_element() == B.get_reference_element() | ||
new_coeffs = construct_new_coeffs(A.get_reference_element(), A, B) | ||
|
||
deg = max(A.get_degree(), B.get_degree()) | ||
em_deg = max(A.get_embedded_degree(), B.get_embedded_degree()) | ||
coeffs = spanning_basis(new_coeffs) | ||
return PolynomialSet(A.get_reference_element(), | ||
A.get_degree(), | ||
A.get_embedded_degree(), | ||
deg, | ||
em_deg, | ||
A.get_expansion_set(), | ||
coeffs) | ||
|
||
|
||
def construct_new_coeffs(ref_el, A, B): | ||
# Constructs new coefficients for the set union of A and B | ||
# If A and B do not have the same degree the smaller one | ||
# is extended to match the larger | ||
|
||
sd = ref_el.get_spatial_dimension() | ||
if A.get_embedded_degree() != B.get_embedded_degree(): | ||
higher = A if A.degree > B.degree else B | ||
lower = B if A.degree > B.degree else A | ||
|
||
try: | ||
sd = lower.get_shape()[0] | ||
except IndexError: | ||
sd = 1 | ||
|
||
embedded_coeffs = [] | ||
diff = higher.coeffs.shape[-1] - lower.coeffs.shape[-1] | ||
for coeff in lower.coeffs: | ||
if sd > 1: | ||
new_coeff = [] | ||
for row in coeff: | ||
new_coeff.append(numpy.append(row, [0 for i in range(diff)])) | ||
embedded_coeffs.append(new_coeff) | ||
else: | ||
embedded_coeffs.append(numpy.append(coeff, [0 for i in range(diff)])) | ||
embedded_coeffs = numpy.array(embedded_coeffs) | ||
new_coeffs = numpy.array(list(embedded_coeffs) + list(higher.coeffs)) | ||
else: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this case works if A and B have the same continuity and degree. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess then this function still needs to handle the case where A and B are not discontinuous but don't have the same degree. I haven't encountered this yet but will add it as a note in the function. |
||
new_coeffs = numpy.array(list(A.coeffs) + list(B.coeffs)) | ||
indiamai marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return new_coeffs | ||
|
||
|
||
class ONSymTensorPolynomialSet(PolynomialSet): | ||
"""Constructs an orthonormal basis for symmetric-tensor-valued | ||
polynomials on a reference element. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
"""Element.""" | ||
# -*- coding: utf-8 -*- | ||
# Copyright (C) 2025 India Marsden | ||
# | ||
# SPDX-License-Identifier: LGPL-3.0-or-later | ||
|
||
from finat.ufl.finiteelementbase import FiniteElementBase | ||
|
||
|
||
class FuseElement(FiniteElementBase): | ||
""" | ||
A finite element defined using FUSE. | ||
|
||
TODO: Need to deal with cases where value shape and reference value shape are different | ||
""" | ||
|
||
def __init__(self, triple, cell=None): | ||
self.triple = triple | ||
if not cell: | ||
cell = self.triple.cell.to_ufl() | ||
|
||
# this isn't really correct | ||
degree = self.triple.spaces[0].degree() | ||
super(FuseElement, self).__init__("IT", cell, degree, None, triple.get_value_shape()) | ||
|
||
def __repr__(self): | ||
return "FiniteElement(%s, %s, (%s, %s, %s), %s)" % ( | ||
repr(self.triple.DOFGenerator), repr(self.triple.cell), repr(self.triple.spaces[0]), repr(self.triple.spaces[1]), repr(self.triple.spaces[2]), "X") | ||
|
||
def __str__(self): | ||
return "<Fuse%sElem on %s>" % (self.triple.spaces[0], self.triple.cell) | ||
|
||
def mapping(self): | ||
if str(self.sobolev_space) == "HCurl": | ||
return "covariant Piola" | ||
elif str(self.sobolev_space) == "HDiv": | ||
return "contravariant Piola" | ||
else: | ||
return "identity" | ||
|
||
def sobolev_space(self): | ||
return self.triple.spaces[1] | ||
|
||
def reconstruct(self, family=None, cell=None, degree=None, quad_scheme=None, variant=None): | ||
return FuseElement(self.triple, cell=cell) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to check also for the continuity of the expansion sets. We throw a ValueError if they are different. This logic would only work for discontinuous expansion sets, and break if the expansion set continuity is "C1".