def estimate_resid(inner_n): nodes = mp.warp_and_blend_nodes(dims, inner_n) basis = mp.orthonormal_basis_for_space( mp.PN(dims, inner_n), mp.Simplex(dims)) vdm = mp.vandermonde(basis.functions, nodes) f = test_func(nodes[0]) coeffs = la.solve(vdm, f) from modepy.modal_decay import estimate_relative_expansion_residual return estimate_relative_expansion_residual( coeffs.reshape(1, -1), dims, inner_n)
def get_simplex_element_flip_matrix(order, unit_nodes, permutation=None): """ Generate a resampling matrix that corresponds to a permutation of the barycentric coordinates being applied. The default permutation is to swap the first two barycentric coordinates. :param order: The order of the function space on the simplex, (see second argument in :fun:`modepy.simplex_best_available_basis`) :param unit_nodes: A np array of unit nodes with shape *(dim, nunit_nodes)* :param permutation: Either *None*, or a tuple of shape storing a permutation: the *i*th barycentric coordinate gets mapped to the *permutation[i]*th coordinate. :return: A numpy array of shape *(nunit_nodes, nunit_nodes)* which, when its transpose is right-applied to the matrix of nodes (shaped *(dim, nunit_nodes)*), corresponds to the permutation being applied """ from modepy.tools import barycentric_to_unit, unit_to_barycentric bary_unit_nodes = unit_to_barycentric(unit_nodes) flipped_bary_unit_nodes = bary_unit_nodes.copy() if permutation is None: flipped_bary_unit_nodes[0, :] = bary_unit_nodes[1, :] flipped_bary_unit_nodes[1, :] = bary_unit_nodes[0, :] else: flipped_bary_unit_nodes[permutation, :] = bary_unit_nodes flipped_unit_nodes = barycentric_to_unit(flipped_bary_unit_nodes) dim = unit_nodes.shape[0] shape = mp.Simplex(dim) space = mp.PN(dim, order) basis = mp.basis_for_space(space, shape) flip_matrix = mp.resampling_matrix(basis.functions, flipped_unit_nodes, unit_nodes) flip_matrix[np.abs(flip_matrix) < 1e-15] = 0 # Flipping twice should be the identity if permutation is None: assert la.norm( np.dot(flip_matrix, flip_matrix) - np.eye(len(flip_matrix))) < 1e-13 return flip_matrix
def test_diff_matrix_permutation(dims): order = 5 space = mp.PN(dims, order) from pytools import \ generate_nonnegative_integer_tuples_summing_to_at_most as gnitstam node_tuples = list(gnitstam(order, dims)) simplex_onb = mp.orthonormal_basis_for_space(space, mp.Simplex(dims)) nodes = np.array(mp.warp_and_blend_nodes(dims, order, node_tuples=node_tuples)) diff_matrices = mp.differentiation_matrices( simplex_onb.functions, simplex_onb.gradients, nodes) for iref_axis in range(dims): perm = mp.diff_matrix_permutation(node_tuples, iref_axis) assert la.norm( diff_matrices[iref_axis] - diff_matrices[0][perm][:, perm]) < 1e-10
def test_modal_decay(case_name, test_func, dims, n, expected_expn): space = mp.PN(dims, n) nodes = mp.warp_and_blend_nodes(dims, n) basis = mp.orthonormal_basis_for_space(space, mp.Simplex(dims)) vdm = mp.vandermonde(basis.functions, nodes) f = test_func(nodes[0]) coeffs = la.solve(vdm, f) if 0: from modepy.tools import plot_element_values plot_element_values(n, nodes, f, resample_n=70, show_nodes=True) from modepy.modal_decay import fit_modal_decay expn, _ = fit_modal_decay(coeffs.reshape(1, -1), dims, n) expn = expn[0] print(f"{case_name}: computed: {expn:g}, expected: {expected_expn:g}") assert abs(expn-expected_expn) < 0.1
def space(self): return mp.PN(self.dim, self.order)
def from_mesh_interp_matrix(self): meg = self.mesh_el_group meg_space = mp.PN(meg.dim, meg.order) return mp.resampling_matrix( mp.basis_for_space(meg_space, self._shape).functions, self.unit_nodes, meg.unit_nodes)