def initialize(self, method): Pusher.initialize(self, method) backend_class = getattr(_internal, "MonomialPusher" + method.get_dimensionality_suffix()) self.backend = backend_class(method.mesh_data) # add monomial basis data --------------------------------------------- from hedge.polynomial import generic_vandermonde from pyrticle._internal import MonomialBasisFunction, lu for i, eg in enumerate(method.mesh_data.discr.element_groups): ldis = eg.local_discretization from pyrticle._internal import LocalMonomialDiscretization lmd = LocalMonomialDiscretization() lmd.basis.extend([MonomialBasisFunction(*idx) for idx in ldis.node_tuples()]) mon_vdm_t = numpy.asarray( generic_vandermonde(ldis.unit_nodes(), lmd.basis).T, order="C") lmd.lu_vandermonde_t, lmd.lu_piv_vandermonde_t = lu(mon_vdm_t) self.backend.local_discretizations.append(lmd) self.backend.ldis_indices.extend([i]*len(eg.members))
def scaled_vandermonde(self, el, eog, points, basis): """The remapping procedure in rec_grid relies on a pseudoinverse minimizing the pointwise error on all found interpolation points. But if an element spans bricks with different resolution, the high-res points get an unfair advantage, because there's so many more of them. Therefore, each point is weighted by its corresponding cell volume, meaning that the corresponding row of the structured Vandermonde matrix must be scaled by this volume, as computed by L{find_points_in_element}. This routine returns the scaled Vandermonde matrix. """ from hedge.polynomial import generic_vandermonde vdm = generic_vandermonde([el.inverse_map(x) for x in points], basis) for i, weight in enumerate(eog.weight_factors): vdm[i] *= weight return 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 scaled_vandermonde(self, el, eog, points, basis): """The remapping procedure in rec_grid relies on a pseudoinverse minimizing the pointwise error on all found interpolation points. But if an element spans bricks with different resolution, the high-res points get an unfair advantage, because there's so many more of them. Therefore, each point is weighted by its corresponding cell volume, meaning that the corresponding row of the structured Vandermonde matrix must be scaled by this volume, as computed by L{find_points_in_element}. This routine returns the scaled Vandermonde matrix. """ from hedge.polynomial import generic_vandermonde vdm = generic_vandermonde( [el.inverse_map(x) for x in points], basis) for i, weight in enumerate(eog.weight_factors): vdm[i] *= weight return 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 matrix(self, eg): class ChebyshevMode: def __init__(self, n): from math import pi self.n = n if n == 0: self.normalization = 1/pi else: self.normalization = 1/(pi/2) def __call__(self, x): from math import acos, cos return cos(self.n*acos(x[0])) from hedge.discretization.local import IntervalDiscretization assert isinstance(eg.local_discretization, IntervalDiscretization) ldis = eg.local_discretization modes = [ChebyshevMode(i) for i in range(ldis.order+1)] from hedge.polynomial import generic_vandermonde vdm = generic_vandermonde(ldis.unit_nodes(), modes) return numpy.asarray(la.inv(vdm), order="C")
def equidistant_vandermonde(self): from hedge.polynomial import generic_vandermonde return generic_vandermonde(list(self.equidistant_unit_nodes()), list(self.basis_functions()))
def equidistant_vandermonde(self): from hedge.polynomial import generic_vandermonde return generic_vandermonde( list(self.equidistant_unit_nodes()), list(self.basis_functions()))
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 face_vandermonde(self): from hedge.polynomial import generic_vandermonde return generic_vandermonde(self.face_nodes, list(self.ldis.face_basis()))
def vandermonde(self): from hedge.polynomial import generic_vandermonde return generic_vandermonde(self.volume_nodes, list(self.ldis.basis_functions()))
def face_vandermonde(self): from hedge.polynomial import generic_vandermonde return generic_vandermonde(self.unit_face_nodes(), self.face_basis())
def face_vandermonde(self): from hedge.polynomial import generic_vandermonde return generic_vandermonde( self.face_nodes, list(self.ldis.face_basis()))
def vandermonde(self): from hedge.polynomial import generic_vandermonde return generic_vandermonde( self.volume_nodes, list(self.ldis.basis_functions()))
def face_vandermonde(self): from hedge.polynomial import generic_vandermonde return generic_vandermonde( self.unit_face_nodes(), self.face_basis())
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)