forked from FEniCS/fiat
-
Notifications
You must be signed in to change notification settings - Fork 7
Walkington C1 macroelement #155
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
Merged
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
b68de43
Morley Tetrahedron
pbrubeck 819f636
Dimension independent zany map
pbrubeck 62d933d
Failing zany test
pbrubeck 51e3930
Fix quadrature degree
pbrubeck dc9edc1
Clean up Bell
pbrubeck cbae4f1
Walkington C1 macroelement
pbrubeck 27d688a
Correct basis_transformation for Morley
pbrubeck 31f1592
Cleanup
pbrubeck 051254c
Register Morley tetrahedron
pbrubeck 3cf0128
Fix factor of 3
pbrubeck da6a3c7
Fix for unimplemented power
pbrubeck 932ef8a
Index-free zany map
pbrubeck f1d42a9
Merge branch 'pbrubeck/morley-tet' into pbrubeck/walkington
pbrubeck 4a74579
Test
pbrubeck 5af9ae6
Cleanup, citation
pbrubeck 79a1dae
cleanup
pbrubeck 9c32f89
Remove if statements
pbrubeck 0fa8079
Merge branch 'pbrubeck/morley-tet' into pbrubeck/walkington
pbrubeck ddb71b1
error
pbrubeck 1df113d
merge conflict
pbrubeck c4a22dc
merge conflict
pbrubeck a812d3c
cite
pbrubeck fb8e712
WIP
pbrubeck cf7c910
WIP
pbrubeck 1fc8f39
Zany magic
pbrubeck a0339ce
register element
pbrubeck 36fdd4b
cleanup
pbrubeck 83a62eb
Merge branch 'main' into pbrubeck/walkington
pbrubeck 64907c0
add mass conditioning test
pbrubeck b966b49
style
pbrubeck 95adf36
tidy
pbrubeck File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| # Copyright (C) 2025 Pablo D. Brubeck | ||
| # | ||
| # This file is part of FIAT (https://www.fenicsproject.org) | ||
| # | ||
| # SPDX-License-Identifier: LGPL-3.0-or-later | ||
|
|
||
| # This is not quite Walkington, but is 65-dofs and includes 20 extra constraint | ||
|
rckirby marked this conversation as resolved.
|
||
| # functionals. The first 45 basis functions are the reference element | ||
| # bfs, but the extra 20 are used in the transformation theory. | ||
|
|
||
| from FIAT import finite_element, polynomial_set, macro | ||
| from FIAT.dual_set import DualSet | ||
| from FIAT.expansions import polynomial_dimension | ||
| from FIAT.functional import ( | ||
| PointEvaluation, PointDerivative, | ||
| IntegralMomentOfNormalDerivative, | ||
| IntegralMomentOfBidirectionalDerivative, | ||
|
pbrubeck marked this conversation as resolved.
|
||
| ) | ||
| from FIAT.reference_element import TETRAHEDRON | ||
| from FIAT.quadrature import FacetQuadratureRule, QuadratureRule | ||
| from FIAT.quadrature_schemes import create_quadrature | ||
| from FIAT.jacobi import eval_jacobi | ||
| import numpy | ||
|
|
||
|
|
||
| class WalkingtonDualSet(DualSet): | ||
| def __init__(self, ref_el, degree): | ||
| top = ref_el.get_topology() | ||
| sd = ref_el.get_spatial_dimension() | ||
| entity_ids = {dim: {entity: [] for entity in top[dim]} for dim in top} | ||
| nodes = [] | ||
|
|
||
| # Vertex dofs: second order jet | ||
| for v in sorted(top[0]): | ||
| cur = len(nodes) | ||
| x, = ref_el.make_points(0, v, degree) | ||
| nodes.append(PointEvaluation(ref_el, x)) | ||
|
|
||
| # first and second derivatives | ||
| nodes.extend(PointDerivative(ref_el, x, alpha) | ||
| for i in (1, 2) for alpha in polynomial_set.mis(sd, i)) | ||
| entity_ids[0][v].extend(range(cur, len(nodes))) | ||
|
|
||
| # Face dofs: moments or normal derivative | ||
| ref_face = ref_el.construct_subelement(2) | ||
| Q_face = create_quadrature(ref_face, degree-1) | ||
| f_at_qpts = numpy.ones(Q_face.get_weights().shape) | ||
| for face in sorted(top[2]): | ||
| cur = len(nodes) | ||
| nodes.append(IntegralMomentOfNormalDerivative(ref_el, face, Q_face, f_at_qpts)) | ||
| entity_ids[2][face].extend(range(cur, len(nodes))) | ||
|
|
||
| # Interior dof: point evaluation at barycenter | ||
| for entity in top[sd]: | ||
| cur = len(nodes) | ||
| x, = ref_el.make_points(sd, entity, sd+1) | ||
| nodes.append(PointEvaluation(ref_el, x)) | ||
| entity_ids[sd][entity].extend(range(cur, len(nodes))) | ||
|
|
||
| # Constraint dofs | ||
| # Face-edge constraint: normal derivative along edge is cubic | ||
| edges = ref_el.get_connectivity()[(2, 1)] | ||
| ref_edge = ref_el.construct_subelement(1) | ||
| Q_edge = create_quadrature(ref_edge, 2*(degree-1)) | ||
| x = ref_edge.compute_barycentric_coordinates(Q_edge.get_points()) | ||
| leg4_at_qpts = eval_jacobi(0, 0, 4, x[:, 1] - x[:, 0]) | ||
| # Face constraint: normal derivative is cubic | ||
| Q_face, phi = face_constraint(ref_face) | ||
|
|
||
| extra_entity_ids = {dim: {entity: [] for entity in top[dim]} for dim in top} | ||
| extra_nodes = [] | ||
|
|
||
| for face in sorted(top[2]): | ||
| cur = len(nodes) | ||
| thats = ref_el.compute_tangents(sd-1, face) | ||
| nface = -numpy.cross(*thats) | ||
| nface /= numpy.linalg.norm(nface) | ||
|
|
||
| for i, e in enumerate(edges[face]): | ||
| Q = FacetQuadratureRule(ref_face, 1, i, Q_edge) | ||
|
|
||
| te = ref_el.compute_edge_tangent(e) | ||
| nfe = numpy.cross(te, nface) | ||
| nfe /= numpy.linalg.norm(nfe) | ||
| nfe /= Q.jacobian_determinant() | ||
| nodes.append(IntegralMomentOfNormalDerivative(ref_el, face, Q, leg4_at_qpts, n=nfe)) | ||
|
|
||
| Q = FacetQuadratureRule(ref_el, 2, face, Q_face) | ||
| f = phi / Q.jacobian_determinant() | ||
| nodes.extend(IntegralMomentOfBidirectionalDerivative(ref_el, Q, f, nface, t) for t in thats) | ||
| entity_ids[2][face].extend(range(cur, len(nodes))) | ||
|
|
||
| cur = len(extra_nodes) | ||
| extra_nodes.extend(IntegralMomentOfBidirectionalDerivative(ref_el, Q, f, thats[i], thats[j]) | ||
|
pbrubeck marked this conversation as resolved.
|
||
| for i in range(2) for j in range(i, 2)) | ||
| extra_entity_ids[2][face].extend(range(cur, len(extra_nodes))) | ||
|
|
||
| self.nodal_completion = DualSet(extra_nodes, ref_el, extra_entity_ids) | ||
| super().__init__(nodes, ref_el, entity_ids) | ||
|
|
||
|
|
||
| class Walkington(finite_element.CiarletElement): | ||
| """The Walkington C1 macroelement.""" | ||
|
|
||
| def __init__(self, ref_el, degree=5): | ||
| if ref_el.get_shape() != TETRAHEDRON: | ||
| raise ValueError(f"{type(self).__name__} only defined on tetrahedron") | ||
| if degree != 5: | ||
| raise ValueError(f"{type(self).__name__} only defined for degree=5.") | ||
|
|
||
| dual = WalkingtonDualSet(ref_el, degree) | ||
| ref_complex = macro.AlfeldSplit(ref_el) | ||
| poly_set = macro.CkPolynomialSet(ref_complex, degree, order=1, vorder=4, variant="bubble") | ||
| super().__init__(poly_set, dual, degree) | ||
|
|
||
|
|
||
| def face_constraint(ref_face): | ||
| k = 3 | ||
| sd = ref_face.get_spatial_dimension() | ||
| Q = create_quadrature(ref_face, 2*k) | ||
| dimPkm1 = polynomial_dimension(ref_face, k-1) | ||
|
|
||
| pts = list(Q.get_points()[:3]) | ||
| pts.append(Q.get_points()[-1]) | ||
| P = polynomial_set.ONPolynomialSet(ref_face, k) | ||
| Pk = P.tabulate(pts)[(0,)*sd][dimPkm1:] | ||
| c = numpy.linalg.solve(Pk.T, [0, 0, 0, 1]) | ||
| Pk = P.tabulate(Q.get_points())[(0,)*sd][dimPkm1:] | ||
| phi = numpy.dot(c, Pk) | ||
|
|
||
| supp = abs(phi) > 1E-12 | ||
| pts = Q.get_points()[supp] | ||
| wts = Q.get_weights()[supp] | ||
| Q = QuadratureRule(ref_face, pts, wts) | ||
| phi = phi[supp] | ||
| return Q, phi | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.