def volume_up_interpolation_matrix(self): from hedge.tools.linalg import leftsolve return numpy.asarray( leftsolve( self.ldis.vandermonde(), self.vandermonde()), order="C")
def make_pointwise_interpolation_matrix(self, eog, eg, el, ldis, svd, scaled_vdm, basis_subset=None): u, s, vt = svd point_count = u.shape[0] node_count = vt.shape[1] thresh = (numpy.finfo(float).eps * max(s.shape) * s[0]) nonzero_flags = numpy.abs(s) >= thresh inv_s = numpy.zeros((len(s),), dtype=float) inv_s[nonzero_flags] = 1/s[nonzero_flags] if not nonzero_flags.all(): from warnings import warn warn("grid dep: taking pseudoinverse of poorly conditioned matrix--" "this should have been caught earlier") # compute the pseudoinverse of the structured Vandermonde matrix inv_s_diag = numpy.zeros( (node_count, point_count), dtype=float) inv_s_diag[:len(s),:len(s)] = numpy.diag(inv_s) svdm_pinv = numpy.dot(numpy.dot(vt.T, inv_s_diag), u.T) # check that it's reasonable pinv_resid = la.norm( numpy.dot(svdm_pinv, scaled_vdm) - numpy.eye(node_count)) if pinv_resid > 1e-8: from warnings import warn warn("rec_grid: bad pseudoinv precision, element=%d, " "#nodes=%d, #sgridpts=%d, resid=%.5g centroid=%s" % (el.id, node_count, point_count, pinv_resid, el.centroid(self.method.discretization.mesh.points))) el_vdm = ldis.vandermonde() if basis_subset is not None: el_vdm = el_vdm[:,basis_subset] imat = numpy.dot(el_vdm, svdm_pinv) if self.filter is not None: imat = numpy.dot(self.filter.get_filter_matrix(eg), imat) assert not numpy.isnan(imat).any(), \ "encountered NaN in element %d's interpolation matrix" % el.id assert not numpy.isinf(imat).any(), \ "encountered infinity in element %d's interpolation matrix" % el.id eog.interpolation_matrix = numpy.asarray(imat, order="F") if basis_subset is None: from hedge.tools import leftsolve eog.inverse_interpolation_matrix = numpy.asarray( leftsolve(el_vdm, scaled_vdm), order="F")
def differentiation_matrices(self): """Return matrices that map the nodal values of a function to the nodal values of its derivative in each of the unit coordinate directions. """ from hedge.tools import leftsolve # see doc/hedge-notes.tm v = self.vandermonde() return [leftsolve(v, vdiff) for vdiff in self.grad_vandermonde()]
def differentiation_matrices(self): """Return matrices that map the nodal values of a function to the nodal values of its derivative in each of the unit coordinate directions. """ from hedge.tools import leftsolve # see doc/hedge-notes.tm v = self.vandermonde() return [ numpy.asarray(leftsolve(v, vdiff), order="C") for vdiff in self.grad_vandermonde() ]
def matrix(self, eg): ldis = eg.local_discretization filter_coeffs = [self.mode_response_func(mid, ldis) for mid in ldis.generate_mode_identifiers()] # build filter matrix vdm = ldis.vandermonde() from hedge.tools import leftsolve mat = np.asarray( leftsolve(vdm, np.dot(vdm, np.diag(filter_coeffs))), order="C") return mat
def matrix(self, eg): ldis = eg.local_discretization filter_coeffs = [ self.mode_response_func(mid, ldis) for mid in ldis.generate_mode_identifiers() ] # build filter matrix vdm = ldis.vandermonde() from hedge.tools import leftsolve mat = np.asarray(leftsolve(vdm, np.dot(vdm, np.diag(filter_coeffs))), order="C") return mat
def volume_to_face_up_interpolation_matrix(self): """Generate a matrix that maps volume nodal values to a vector of face nodal values on the quadrature grid, with faces immediately concatenated, i.e:: [face 1 nodal data][face 2 nodal data]... """ ldis = self.ldis face_maps = ldis.face_affine_maps() from pytools import flatten face_nodes = list( flatten([face_map(qnode) for qnode in self.face_nodes] for face_map in face_maps)) from hedge.polynomial import generic_vandermonde vdm = generic_vandermonde(face_nodes, list(ldis.basis_functions())) from hedge.tools.linalg import leftsolve return leftsolve(self.ldis.vandermonde(), vdm)
def volume_to_face_up_interpolation_matrix(self): """Generate a matrix that maps volume nodal values to a vector of face nodal values on the quadrature grid, with faces immediately concatenated, i.e:: [face 1 nodal data][face 2 nodal data]... """ ldis = self.ldis face_maps = ldis.face_affine_maps() from pytools import flatten face_nodes = list(flatten([face_map(qnode) for qnode in self.face_nodes] for face_map in face_maps)) from hedge.polynomial import generic_vandermonde vdm = generic_vandermonde(face_nodes, list(ldis.basis_functions())) from hedge.tools.linalg import leftsolve return leftsolve(self.ldis.vandermonde(), vdm)
def prepare_with_brick_interpolation(self): class TensorProductLegendreBasisFunc: def __init__(self, n): from hedge.polynomial import LegendreFunction self.funcs = [LegendreFunction(n_i) for n_i in n] def __call__(self, x): result = 1 for f_i, x_i in zip(self.funcs, x): result *= f_i(x_i) return result def make_legendre_basis(dimensions): from pytools import generate_nonnegative_integer_tuples_below return [ TensorProductLegendreBasisFunc(n) for n in generate_nonnegative_integer_tuples_below(dimensions) ] discr = self.method.discretization backend = self.backend backend.elements_on_grid.reserve( sum(len(eg.members) for eg in discr.element_groups)) from pyrticle._internal import ElementOnGrid, BoxFloat total_points = 0 # Iterate over all elements for eg in discr.element_groups: ldis = eg.local_discretization for el in eg.members: el_bbox = BoxFloat(*el.bounding_box(discr.mesh.points)) scaled_tolerance = self.el_tolerance * la.norm( el.map.matrix, 2) el_bbox.lower -= scaled_tolerance el_bbox.upper += scaled_tolerance # For each brick, find all element nodes that lie in it for brk in backend.bricks: eog = ElementOnGrid() eog.element_number = el.id brk_bbox = brk.bounding_box() brk_and_el = brk_bbox.intersect(el_bbox) if brk_and_el.is_empty(): continue el_nodes = [] el_node_indices = [] el_slice = discr.find_el_range(el.id) el_length = el_slice.stop - el_slice.start if brk_and_el == el_bbox: # whole element in brick? fantastic. el_nodes = discr.nodes[el_slice] el_node_indices = range(el_length) else: # no? go through the nodes one by one. for i, node in enumerate(discr.nodes[el_slice]): # this containment check has to be exact, # we positively cannot have nodes belong to # two bricks if brk_bbox.contains(node, threshold=0): el_nodes.append(node) el_node_indices.append(i) idx_range = brk.index_range(brk_and_el) lb = make_legendre_basis(idx_range.upper - idx_range.lower) from hedge.polynomial import generic_vandermonde brk_and_el_points = [ brk.point(c) for c in self.iterator_type(brk, idx_range) ] svdm = generic_vandermonde(points=brk_and_el_points, functions=lb) total_points += len(brk_and_el_points) mixed_vdm_pre = generic_vandermonde(points=el_nodes, functions=lb) if len(el_nodes) < el_length: mixed_vdm = numpy.zeros((el_length, len(lb)), dtype=float) for i, vdm_row in enumerate(mixed_vdm_pre): mixed_vdm[el_node_indices[i]] = vdm_row else: mixed_vdm = mixed_vdm_pre from hedge.tools import leftsolve eog.interpolation_matrix = numpy.asarray(leftsolve( svdm, mixed_vdm), order="Fortran") #print eog.interpolation_matrix.shape #raw_input() eog.grid_nodes.extend( brk.index(c) for c in self.iterator_type(brk, idx_range)) eog.weight_factors = numpy.ones((len(eog.grid_nodes), ), dtype=numpy.float64) backend.elements_on_grid.append(eog) # we don't need no stinkin' extra points backend.extra_point_brick_starts.extend([0] * (len(backend.bricks) + 1)) # stats self.generate_point_statistics(0)
def make_pointwise_interpolation_matrix(self, eog, eg, el, ldis, svd, scaled_vdm, basis_subset=None): u, s, vt = svd point_count = u.shape[0] node_count = vt.shape[1] thresh = (numpy.finfo(float).eps * max(s.shape) * s[0]) nonzero_flags = numpy.abs(s) >= thresh inv_s = numpy.zeros((len(s), ), dtype=float) inv_s[nonzero_flags] = 1 / s[nonzero_flags] if not nonzero_flags.all(): from warnings import warn warn( "grid dep: taking pseudoinverse of poorly conditioned matrix--" "this should have been caught earlier") # compute the pseudoinverse of the structured Vandermonde matrix inv_s_diag = numpy.zeros((node_count, point_count), dtype=float) inv_s_diag[:len(s), :len(s)] = numpy.diag(inv_s) svdm_pinv = numpy.dot(numpy.dot(vt.T, inv_s_diag), u.T) # check that it's reasonable pinv_resid = la.norm( numpy.dot(svdm_pinv, scaled_vdm) - numpy.eye(node_count)) if pinv_resid > 1e-8: from warnings import warn warn("rec_grid: bad pseudoinv precision, element=%d, " "#nodes=%d, #sgridpts=%d, resid=%.5g centroid=%s" % (el.id, node_count, point_count, pinv_resid, el.centroid(self.method.discretization.mesh.points))) el_vdm = ldis.vandermonde() if basis_subset is not None: el_vdm = el_vdm[:, basis_subset] imat = numpy.dot(el_vdm, svdm_pinv) if self.filter is not None: imat = numpy.dot(self.filter.get_filter_matrix(eg), imat) assert not numpy.isnan(imat).any(), \ "encountered NaN in element %d's interpolation matrix" % el.id assert not numpy.isinf(imat).any(), \ "encountered infinity in element %d's interpolation matrix" % el.id eog.interpolation_matrix = numpy.asarray(imat, order="F") if basis_subset is None: from hedge.tools import leftsolve eog.inverse_interpolation_matrix = numpy.asarray(leftsolve( el_vdm, scaled_vdm), order="F")
def face_up_interpolation_matrix(self): from hedge.tools.linalg import leftsolve return leftsolve(self.ldis.face_vandermonde(), self.face_vandermonde())
def volume_up_interpolation_matrix(self): from hedge.tools.linalg import leftsolve return numpy.asarray(leftsolve(self.ldis.vandermonde(), self.vandermonde()), order="C")
def face_up_interpolation_matrix(self): from hedge.tools.linalg import leftsolve return leftsolve( self.ldis.face_vandermonde(), self.face_vandermonde())
def prepare_with_brick_interpolation(self): class TensorProductLegendreBasisFunc: def __init__(self, n): from hedge.polynomial import LegendreFunction self.funcs = [LegendreFunction(n_i) for n_i in n] def __call__(self, x): result = 1 for f_i, x_i in zip(self.funcs, x): result *= f_i(x_i) return result def make_legendre_basis(dimensions): from pytools import generate_nonnegative_integer_tuples_below return [TensorProductLegendreBasisFunc(n) for n in generate_nonnegative_integer_tuples_below(dimensions)] discr = self.method.discretization backend = self.backend backend.elements_on_grid.reserve( sum(len(eg.members) for eg in discr.element_groups)) from pyrticle._internal import ElementOnGrid, BoxFloat total_points = 0 # Iterate over all elements for eg in discr.element_groups: ldis = eg.local_discretization for el in eg.members: el_bbox = BoxFloat(*el.bounding_box(discr.mesh.points)) scaled_tolerance = self.el_tolerance * la.norm(el.map.matrix, 2) el_bbox.lower -= scaled_tolerance el_bbox.upper += scaled_tolerance # For each brick, find all element nodes that lie in it for brk in backend.bricks: eog = ElementOnGrid() eog.element_number = el.id brk_bbox = brk.bounding_box() brk_and_el = brk_bbox.intersect(el_bbox) if brk_and_el.is_empty(): continue el_nodes = [] el_node_indices = [] el_slice = discr.find_el_range(el.id) el_length = el_slice.stop-el_slice.start if brk_and_el == el_bbox: # whole element in brick? fantastic. el_nodes = discr.nodes[el_slice] el_node_indices = range(el_length) else: # no? go through the nodes one by one. for i, node in enumerate(discr.nodes[el_slice]): # this containment check has to be exact, # we positively cannot have nodes belong to # two bricks if brk_bbox.contains(node, threshold=0): el_nodes.append(node) el_node_indices.append(i) idx_range = brk.index_range(brk_and_el) lb = make_legendre_basis(idx_range.upper-idx_range.lower) from hedge.polynomial import generic_vandermonde brk_and_el_points = [brk.point(c) for c in self.iterator_type(brk, idx_range)] svdm = generic_vandermonde( points=brk_and_el_points, functions=lb) total_points += len(brk_and_el_points) mixed_vdm_pre = generic_vandermonde( points=el_nodes, functions=lb) if len(el_nodes) < el_length: mixed_vdm = numpy.zeros((el_length, len(lb)), dtype=float) for i, vdm_row in enumerate(mixed_vdm_pre): mixed_vdm[el_node_indices[i]] = vdm_row else: mixed_vdm = mixed_vdm_pre from hedge.tools import leftsolve eog.interpolation_matrix = numpy.asarray( leftsolve(svdm, mixed_vdm), order="Fortran") #print eog.interpolation_matrix.shape #raw_input() eog.grid_nodes.extend(brk.index(c) for c in self.iterator_type(brk, idx_range)) eog.weight_factors = numpy.ones( (len(eog.grid_nodes),), dtype=numpy.float64) backend.elements_on_grid.append(eog) # we don't need no stinkin' extra points backend.extra_point_brick_starts.extend([0]*(len(backend.bricks)+1)) # stats self.generate_point_statistics(0)