def test_TFE_2Dx1D_vector_triangle_hcurl_rotate(): S = UFCTriangle() T = UFCInterval() RT1 = RaviartThomas(S, 1) P1 = Lagrange(T, 1) elt = Hcurl(TensorProductElement(RT1, P1)) assert elt.value_shape() == (3,) tab = elt.tabulate(1, [(0.1, 0.2, 0.3)]) tabA = RT1.tabulate(1, [(0.1, 0.2)]) tabB = P1.tabulate(1, [(0.3,)]) for da, db in [[(0, 0), (0,)], [(1, 0), (0,)], [(0, 1), (0,)], [(0, 0), (1,)]]: dc = da + db assert np.isclose(tab[dc][0][0][0], -tabA[da][0][1][0]*tabB[db][0][0]) assert np.isclose(tab[dc][1][0][0], -tabA[da][0][1][0]*tabB[db][1][0]) assert np.isclose(tab[dc][2][0][0], -tabA[da][1][1][0]*tabB[db][0][0]) assert np.isclose(tab[dc][3][0][0], -tabA[da][1][1][0]*tabB[db][1][0]) assert np.isclose(tab[dc][4][0][0], -tabA[da][2][1][0]*tabB[db][0][0]) assert np.isclose(tab[dc][5][0][0], -tabA[da][2][1][0]*tabB[db][1][0]) assert np.isclose(tab[dc][0][1][0], tabA[da][0][0][0]*tabB[db][0][0]) assert np.isclose(tab[dc][1][1][0], tabA[da][0][0][0]*tabB[db][1][0]) assert np.isclose(tab[dc][2][1][0], tabA[da][1][0][0]*tabB[db][0][0]) assert np.isclose(tab[dc][3][1][0], tabA[da][1][0][0]*tabB[db][1][0]) assert np.isclose(tab[dc][4][1][0], tabA[da][2][0][0]*tabB[db][0][0]) assert np.isclose(tab[dc][5][1][0], tabA[da][2][0][0]*tabB[db][1][0]) assert tab[dc][0][2][0] == 0.0 assert tab[dc][1][2][0] == 0.0 assert tab[dc][2][2][0] == 0.0 assert tab[dc][3][2][0] == 0.0 assert tab[dc][4][2][0] == 0.0 assert tab[dc][5][2][0] == 0.0
def _generate_cell_dofs(self, cell, degree, offset, variant, quad_deg): """Generate degrees of freedoms (dofs) for entities of codimension d (cells).""" # Return empty info if not applicable d = cell.get_spatial_dimension() if (d == 2 and degree < 2) or (d == 3 and degree < 3): return ([], {0: []}) # Create quadrature points Q = make_quadrature(cell, 2 * (degree + 1)) qs = Q.get_points() # Create Raviart-Thomas nodal basis RT = RaviartThomas(cell, degree + 1 - d, variant) phi = RT.get_nodal_basis() # Evaluate Raviart-Thomas basis at quadrature points phi_at_qs = phi.tabulate(qs)[(0,) * d] # Use (Frobenius) integral moments against RTs as dofs dofs = [IntegralMoment(cell, Q, phi_at_qs[i, :]) for i in range(len(phi_at_qs))] # Associate these dofs with the interior ids = {0: list(range(offset, offset + len(dofs)))} return (dofs, ids)
def _generate_cell_dofs(self, cell, degree, offset): """Generate degrees of freedoms (dofs) for entities of codimension d (cells).""" # Return empty info if not applicable d = cell.get_spatial_dimension() if (d == 2 and degree < 2) or (d == 3 and degree < 3): return ([], {0: []}) # Create quadrature points Q = make_quadrature(cell, 2 * (degree + 1)) qs = Q.get_points() # Create Raviart-Thomas nodal basis RT = RaviartThomas(cell, degree + 1 - d) phi = RT.get_nodal_basis() # Evaluate Raviart-Thomas basis at quadrature points phi_at_qs = phi.tabulate(qs)[(0,) * d] # Use (Frobenius) integral moments against RTs as dofs dofs = [IntegralMoment(cell, Q, phi_at_qs[i, :]) for i in range(len(phi_at_qs))] # Associate these dofs with the interior ids = {0: list(range(offset, offset + len(dofs)))} return (dofs, ids)
def test_TFE_2Dx1D_vector_triangle_hdiv(): S = UFCTriangle() T = UFCInterval() RT1 = RaviartThomas(S, 1) P1_DG = DiscontinuousLagrange(T, 1) elt = Hdiv(TensorProductElement(RT1, P1_DG)) assert elt.value_shape() == (3, ) tab = elt.tabulate(1, [(0.1, 0.2, 0.3)]) tabA = RT1.tabulate(1, [(0.1, 0.2)]) tabB = P1_DG.tabulate(1, [(0.3, )]) for da, db in [[(0, 0), (0, )], [(1, 0), (0, )], [(0, 1), (0, )], [(0, 0), (1, )]]: dc = da + db assert np.isclose(tab[dc][0][0][0], tabA[da][0][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][1][0][0], tabA[da][0][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][2][0][0], tabA[da][1][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][3][0][0], tabA[da][1][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][4][0][0], tabA[da][2][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][5][0][0], tabA[da][2][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][0][1][0], tabA[da][0][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][1][1][0], tabA[da][0][1][0] * tabB[db][1][0]) assert np.isclose(tab[dc][2][1][0], tabA[da][1][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][3][1][0], tabA[da][1][1][0] * tabB[db][1][0]) assert np.isclose(tab[dc][4][1][0], tabA[da][2][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][5][1][0], tabA[da][2][1][0] * tabB[db][1][0]) assert tab[dc][0][2][0] == 0.0 assert tab[dc][1][2][0] == 0.0 assert tab[dc][2][2][0] == 0.0 assert tab[dc][3][2][0] == 0.0 assert tab[dc][4][2][0] == 0.0 assert tab[dc][5][2][0] == 0.0
def test_nodal_enriched_implementation(): """Following element pair should be the same. This might be fragile to dof reordering but works now. """ e0 = RaviartThomas(T, 2) e1 = NodalEnrichedElement( RestrictedElement(RaviartThomas(T, 2), restriction_domain='facet'), RestrictedElement(RaviartThomas(T, 2), restriction_domain='interior') ) for attr in ["degree", "get_reference_element", "entity_dofs", "entity_closure_dofs", "get_formdegree", "mapping", "num_sub_elements", "space_dimension", "value_shape", "is_nodal", ]: assert getattr(e0, attr)() == getattr(e1, attr)() assert np.allclose(e0.get_coeffs(), e1.get_coeffs()) assert np.allclose(e0.dmats(), e1.dmats()) assert np.allclose(e0.get_dual_set().to_riesz(e0.get_nodal_basis()), e1.get_dual_set().to_riesz(e1.get_nodal_basis()))
def _generate_face_dofs(self, cell, degree, offset, variant, quad_deg): """Generate degrees of freedoms (dofs) for faces.""" # Initialize empty dofs and identifiers (ids) dofs = [] ids = dict(list(zip(list(range(4)), ([] for i in range(4))))) # Return empty info if not applicable d = cell.get_spatial_dimension() if (degree < 2): return (dofs, ids) msg = "2nd kind Nedelec face dofs only available with UFC convention" assert isinstance(cell, UFCTetrahedron), msg # Iterate over the faces of the tet num_faces = len(cell.get_topology()[2]) for face in range(num_faces): # Construct quadrature scheme for this face m = 2 * (degree + 1) Q_face = UFCTetrahedronFaceQuadratureRule(face, m) # Construct Raviart-Thomas of (degree - 1) on the # reference face reference_face = Q_face.reference_rule().ref_el RT = RaviartThomas(reference_face, degree - 1, variant) num_rts = RT.space_dimension() # Evaluate RT basis functions at reference quadrature # points ref_quad_points = Q_face.reference_rule().get_points() num_quad_points = len(ref_quad_points) Phi = RT.get_nodal_basis() Phis = Phi.tabulate(ref_quad_points)[(0, 0)] # Note: Phis has dimensions: # num_basis_functions x num_components x num_quad_points # Map Phis -> phis (reference values to physical values) J = Q_face.jacobian() scale = 1.0 / numpy.sqrt(numpy.linalg.det(numpy.dot(J.T, J))) phis = numpy.ndarray((d, num_quad_points)) for i in range(num_rts): for q in range(num_quad_points): phi_i_q = scale * numpy.dot(J, Phis[numpy.newaxis, i, :, q].T) for j in range(d): phis[j, q] = phi_i_q[j] # Construct degrees of freedom as integral moments on # this cell, using the special face quadrature # weighted against the values of the (physical) # Raviart--Thomas'es on the face dofs += [IntegralMoment(cell, Q_face, phis)] # Assign identifiers (num RTs per face + previous edge dofs) ids[face] = list(range(offset + num_rts*face, offset + num_rts*(face + 1))) return (dofs, ids)
def _generate_face_dofs(self, cell, degree, offset): """Generate degrees of freedoms (dofs) for faces.""" # Initialize empty dofs and identifiers (ids) dofs = [] ids = dict(list(zip(list(range(4)), ([] for i in range(4))))) # Return empty info if not applicable d = cell.get_spatial_dimension() if (degree < 2): return (dofs, ids) msg = "2nd kind Nedelec face dofs only available with UFC convention" assert isinstance(cell, UFCTetrahedron), msg # Iterate over the faces of the tet num_faces = len(cell.get_topology()[2]) for face in range(num_faces): # Construct quadrature scheme for this face m = 2 * (degree + 1) Q_face = UFCTetrahedronFaceQuadratureRule(face, m) # Construct Raviart-Thomas of (degree - 1) on the # reference face reference_face = Q_face.reference_rule().ref_el RT = RaviartThomas(reference_face, degree - 1) num_rts = RT.space_dimension() # Evaluate RT basis functions at reference quadrature # points ref_quad_points = Q_face.reference_rule().get_points() num_quad_points = len(ref_quad_points) Phi = RT.get_nodal_basis() Phis = Phi.tabulate(ref_quad_points)[(0, 0)] # Note: Phis has dimensions: # num_basis_functions x num_components x num_quad_points # Map Phis -> phis (reference values to physical values) J = Q_face.jacobian() scale = 1.0 / numpy.sqrt(numpy.linalg.det(numpy.dot(J.T, J))) phis = numpy.ndarray((d, num_quad_points)) for i in range(num_rts): for q in range(num_quad_points): phi_i_q = scale * numpy.dot(J, Phis[numpy.newaxis, i, :, q].T) for j in range(d): phis[j, q] = phi_i_q[j] # Construct degrees of freedom as integral moments on # this cell, using the special face quadrature # weighted against the values of the (physical) # Raviart--Thomas'es on the face dofs += [IntegralMoment(cell, Q_face, phis)] # Assign identifiers (num RTs per face + previous edge dofs) ids[face] = list(range(offset + num_rts*face, offset + num_rts*(face + 1))) return (dofs, ids)
def test_mixed_is_not_nodal(): element = MixedElement([ EnrichedElement( RaviartThomas(T, 1), RestrictedElement(RaviartThomas(T, 2), restriction_domain="interior")), DiscontinuousLagrange(T, 1) ]) assert not element.is_nodal()
def test_nodal_enriched_implementation(): """Following element pair should be the same. This might be fragile to dof reordering but works now. """ e0 = RaviartThomas(T, 2) e1 = NodalEnrichedElement( RestrictedElement(RaviartThomas(T, 2), restriction_domain='facet'), RestrictedElement(RaviartThomas(T, 2), restriction_domain='interior')) for attr in [ "degree", "get_reference_element", "entity_dofs", "entity_closure_dofs", "get_formdegree", "mapping", "num_sub_elements", "space_dimension", "value_shape", "is_nodal", ]: assert getattr(e0, attr)() == getattr(e1, attr)() assert np.allclose(e0.get_coeffs(), e1.get_coeffs()) assert np.allclose(e0.dmats(), e1.dmats()) assert np.allclose(e0.get_dual_set().to_riesz(e0.get_nodal_basis()), e1.get_dual_set().to_riesz(e1.get_nodal_basis()))
def test_mixed_is_nodal(): element = MixedElement([DiscontinuousLagrange(T, 1), RaviartThomas(T, 2)]) assert element.is_nodal()