-
Notifications
You must be signed in to change notification settings - Fork 7
Add fuse element infrastructure #127
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
base: main
Are you sure you want to change the base?
Changes from 29 commits
6573217
dc5188a
c75efef
dfd1347
21f1bf1
3eb0d1a
2c21e27
2b45bd5
9b05688
3a7bb5b
8d1a074
b72cd61
a89d057
ac81474
9420a6d
be81de3
2e3ed6c
0b593e5
263dad1
ad63ee0
3a5b073
8d52e22
8eaa60c
d3b31cb
b5e41fe
f31fd72
a91c7a2
2bc3161
4953241
e8aaa56
a726c98
7d5ef1c
9e2f7c0
2f8a74d
8771342
2373db4
3482800
ef6c59c
df581a7
dde1c05
f04175e
ab73328
85cef62
e665761
53bc284
a4a887c
4633e7f
720e2fa
63e381f
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,49 @@ 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 are discontinuous and do not have the same degree the smaller one | ||
| is extended to match the larger. | ||
|
|
||
| This does not handle the case that A and B have continuity but not the same degree. | ||
| """ | ||
|
|
||
| if A.get_expansion_set().continuity != B.get_expansion_set().continuity: | ||
| raise ValueError("Continuity of expansion sets does not match.") | ||
|
|
||
| if A.get_embedded_degree() != B.get_embedded_degree() and A.get_expansion_set().continuity is None: | ||
| higher = A if A.get_embedded_degree() > B.get_embedded_degree() else B | ||
| lower = B if A.get_embedded_degree() > B.get_embedded_degree() else A | ||
|
|
||
| diff = higher.coeffs.shape[-1] - lower.coeffs.shape[-1] | ||
|
|
||
| # pad only the 0th axis with the difference in size | ||
| padding = [(0, 0) for i in range(len(lower.coeffs.shape) - 1)] + [(0, diff)] | ||
| embedded_coeffs = numpy.pad(lower.coeffs, padding) | ||
|
|
||
| new_coeffs = numpy.concatenate((embedded_coeffs, higher.coeffs), axis=0) | ||
| elif A.get_embedded_degree() == B.get_embedded_degree(): | ||
| new_coeffs = numpy.concatenate((A.coeffs, B.coeffs), axis=0) | ||
| 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.
Author
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. |
||
| raise NotImplementedError("Extending of coefficients is not implemented for PolynomialSets with continuity and different degrees") | ||
| 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 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -518,7 +518,8 @@ def make_points(self, dim, entity_id, order, variant=None, interior=1): | |||||||||
| facet of dimension dim. Order indicates how many points to | ||||||||||
| include in each direction.""" | ||||||||||
| if dim == 0: | ||||||||||
| return (self.get_vertices()[entity_id], ) | ||||||||||
| return (self.get_vertices()[self.get_topology()[dim][entity_id][0]],) | ||||||||||
| # return (self.get_vertices()[entity_id], ) | ||||||||||
|
Comment on lines
+548
to
+549
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.
Suggested change
|
||||||||||
| elif 0 < dim <= self.get_spatial_dimension(): | ||||||||||
| entity_verts = \ | ||||||||||
| self.get_vertices_of_subcomplex( | ||||||||||
|
|
@@ -1343,6 +1344,93 @@ def extrinsic_orientation_permutation_map(self): | |||||||||
| return a | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class Hypercube(Cell): | ||||||||||
| """ | ||||||||||
| For reference elements based on TensorProductCells""" | ||||||||||
| def __init__(self, product): | ||||||||||
| pt = product.get_topology() | ||||||||||
|
|
||||||||||
| verts = product.get_vertices() | ||||||||||
| topology = flatten_entities(pt) | ||||||||||
|
|
||||||||||
| # TODO this should be generalised ? | ||||||||||
| cube_types = {2: QUADRILATERAL, 3: HEXAHEDRON} | ||||||||||
| super().__init__(cube_types[sum(product.get_dimension())], verts, topology) | ||||||||||
|
|
||||||||||
| self.product = product | ||||||||||
| self.unflattening_map = compute_unflattening_map(pt) | ||||||||||
|
|
||||||||||
| def get_dimension(self): | ||||||||||
| """Returns the subelement dimension of the cell. Same as the | ||||||||||
| spatial dimension.""" | ||||||||||
| return self.get_spatial_dimension() | ||||||||||
|
|
||||||||||
| def get_entity_transform(self, dim, entity_i): | ||||||||||
| """Returns a mapping of point coordinates from the | ||||||||||
| `entity_i`-th subentity of dimension `dim` to the cell. | ||||||||||
|
|
||||||||||
| :arg dim: entity dimension (integer) | ||||||||||
| :arg entity_i: entity number (integer) | ||||||||||
| """ | ||||||||||
| d, e = self.unflattening_map[(dim, entity_i)] | ||||||||||
| return self.product.get_entity_transform(d, e) | ||||||||||
|
|
||||||||||
| def volume(self): | ||||||||||
| """Computes the volume in the appropriate dimensional measure.""" | ||||||||||
| return self.product.volume() | ||||||||||
|
|
||||||||||
| def compute_reference_normal(self, facet_dim, facet_i): | ||||||||||
| """Returns the unit normal in infinity norm to facet_i.""" | ||||||||||
| assert facet_dim == 1 | ||||||||||
| d, i = self.unflattening_map[(facet_dim, facet_i)] | ||||||||||
| return self.product.compute_reference_normal(d, i) | ||||||||||
|
|
||||||||||
| def contains_point(self, point, epsilon=0): | ||||||||||
| """Checks if reference cell contains given point | ||||||||||
| (with numerical tolerance as given by the L1 distance (aka 'manhatten', | ||||||||||
| 'taxicab' or rectilinear distance) to the cell. | ||||||||||
|
|
||||||||||
| Parameters | ||||||||||
| ---------- | ||||||||||
| point : numpy.ndarray, list or symbolic expression | ||||||||||
| The coordinates of the point. | ||||||||||
| epsilon : float | ||||||||||
| The tolerance for the check. | ||||||||||
|
|
||||||||||
| Returns | ||||||||||
| ------- | ||||||||||
| bool : True if the point is inside the cell, False otherwise. | ||||||||||
|
|
||||||||||
| """ | ||||||||||
| return self.product.contains_point(point, epsilon=epsilon) | ||||||||||
|
|
||||||||||
| def distance_to_point_l1(self, point, rescale=False): | ||||||||||
| """Get the L1 distance (aka 'manhatten', 'taxicab' or rectilinear | ||||||||||
| distance) to a point with 0.0 if the point is inside the cell. | ||||||||||
|
|
||||||||||
| For more information see the docstring for the UFCSimplex method.""" | ||||||||||
| return self.product.distance_to_point_l1(point, rescale=rescale) | ||||||||||
|
|
||||||||||
| def symmetry_group_size(self, dim): | ||||||||||
| return [1, 2, 8][dim] | ||||||||||
|
|
||||||||||
| def cell_orientation_reflection_map(self): | ||||||||||
| """Return the map indicating whether each possible cell orientation causes reflection (``1``) or not (``0``).""" | ||||||||||
| return self.product.cell_orientation_reflection_map() | ||||||||||
|
|
||||||||||
| def __gt__(self, other): | ||||||||||
| return self.product > other | ||||||||||
|
|
||||||||||
| def __lt__(self, other): | ||||||||||
| return self.product < other | ||||||||||
|
|
||||||||||
| def __ge__(self, other): | ||||||||||
| return self.product >= other | ||||||||||
|
|
||||||||||
| def __le__(self, other): | ||||||||||
| return self.product <= other | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class UFCQuadrilateral(Cell): | ||||||||||
| r"""This is the reference quadrilateral with vertices | ||||||||||
| (0.0, 0.0), (0.0, 1.0), (1.0, 0.0) and (1.0, 1.0). | ||||||||||
|
|
@@ -1734,17 +1822,22 @@ def tuple_sum(tree): | |||||||||
|
|
||||||||||
|
|
||||||||||
| def is_hypercube(cell): | ||||||||||
| res = False | ||||||||||
| if isinstance(cell, (DefaultLine, UFCInterval, UFCQuadrilateral, UFCHexahedron)): | ||||||||||
| return True | ||||||||||
| res = True | ||||||||||
| elif isinstance(cell, TensorProductCell): | ||||||||||
| return reduce(lambda a, b: a and b, [is_hypercube(c) for c in cell.cells]) | ||||||||||
| res = reduce(lambda a, b: a and b, [is_hypercube(c) for c in cell.cells]) | ||||||||||
| else: | ||||||||||
| return False | ||||||||||
| res = False | ||||||||||
| res2 = len(cell.vertices()) == 2 ** cell.get_dimension() | ||||||||||
| assert res == res2 | ||||||||||
| return res | ||||||||||
|
|
||||||||||
|
|
||||||||||
| def flatten_reference_cube(ref_el): | ||||||||||
| """This function flattens a Tensor Product hypercube to the corresponding UFC hypercube""" | ||||||||||
| flattened_cube = {2: UFCQuadrilateral(), 3: UFCHexahedron()} | ||||||||||
| from finat import as_fiat_cell | ||||||||||
| flattened_cube = {2: as_fiat_cell("quadrilateral"), 3: as_fiat_cell("hexahedron")} | ||||||||||
| if numpy.sum(ref_el.get_dimension()) <= 1: | ||||||||||
| # Just return point/interval cell arguments | ||||||||||
| return ref_el | ||||||||||
|
|
@@ -1797,6 +1890,7 @@ def compute_unflattening_map(topology_dict): | |||||||||
|
|
||||||||||
|
|
||||||||||
| def max_complex(complexes): | ||||||||||
| breakpoint() | ||||||||||
| max_cell = max(complexes) | ||||||||||
| if all(max_cell >= b for b in complexes): | ||||||||||
| return max_cell | ||||||||||
|
|
||||||||||
Uh oh!
There was an error while loading. Please reload this page.