def make_rect_mesh_with_corner(a=(0,0), b=(1,1), max_area=None, boundary_tagger=(lambda fvi, el, fn, all_v: []), corner_fraction=(0.3, 0.3), refine_func=None): """Create an unstructured rectangular mesh with a reentrant corner at (-x, -y). :param a: the lower left hand point of the rectangle :param b: the upper right hand point of the rectangle :param max_area: maximum area of each triangle. :param refine_func: A refinement function as taken by :func:`meshpy.triangle.build`. :param corner_fraction: Tuple of fraction of the width taken up by the rentrant corner. """ if max_area is not None: if refine_func is not None: raise ValueError, "cannot specify both refine_func and max_area" def refine_func(vertices, area): return area > max_area marker2tag = { 1: "minus_x", 2: "minus_y", 3: "plus_x", 4: "plus_y", 4: "plus_y", 5: "corner_plus_y", 6: "corner_plus_x", } a = numpy.asarray(a) b = numpy.asarray(b) diag = b-a w = diag.copy(); w[1] = 0 h = diag.copy(); h[0] = 0 points = [ a+h*corner_fraction[1], a+h*corner_fraction[1]+w*corner_fraction[0], a+w*corner_fraction[0], a+w, a+w+h, a+h, ] facets = list(_round_trip_connect(0, 5)) facet_markers = [5,6,2,3,4,1] import meshpy.triangle as triangle mesh_info = triangle.MeshInfo() mesh_info.set_points(points) mesh_info.set_facets(facets, facet_markers) generated_mesh = triangle.build(mesh_info, refinement_func=refine_func) from hedge.mesh import make_conformal_mesh return make_conformal_mesh( generated_mesh.points, generated_mesh.elements, boundary_tagger)
def make_single_element_mesh(a=-0.5, b=0.5, boundary_tagger=(lambda vertices, face_indices: [])): n = 2 node_dict = {} points = [] points_1d = numpy.linspace(a, b, n) for j in range(n): for i in range(n): node_dict[i, j] = len(points) points.append(numpy.array([points_1d[i], points_1d[j]])) elements = [( node_dict[1, 1], node_dict[0, 1], node_dict[1, 0], )] boundary_faces = [(3, 1), (1, 2), (2, 3)] boundary_tags = dict( (frozenset(seg), boundary_tagger(points, seg)) for seg in boundary_faces) from hedge.mesh import make_conformal_mesh return make_conformal_mesh( points, elements, boundary_tags)
def make_rect_mesh_with_corner(a=(0, 0), b=(1, 1), max_area=None, boundary_tagger=(lambda fvi, el, fn, all_v: []), corner_fraction=(0.3, 0.3), refine_func=None): """Create an unstructured rectangular mesh with a reentrant corner at (-x, -y). :param a: the lower left hand point of the rectangle :param b: the upper right hand point of the rectangle :param max_area: maximum area of each triangle. :param refine_func: A refinement function as taken by :func:`meshpy.triangle.build`. :param corner_fraction: Tuple of fraction of the width taken up by the rentrant corner. """ if max_area is not None: if refine_func is not None: raise ValueError("cannot specify both refine_func and max_area") def refine_func(vertices, area): return area > max_area a = numpy.asarray(a) b = numpy.asarray(b) diag = b-a w = diag.copy() w[1] = 0 h = diag.copy() h[0] = 0 points = [ a+h*corner_fraction[1], a+h*corner_fraction[1]+w*corner_fraction[0], a+w*corner_fraction[0], a+w, a+w+h, a+h, ] facets = list(_round_trip_connect(0, 5)) facet_markers = [5, 6, 2, 3, 4, 1] import meshpy.triangle as triangle mesh_info = triangle.MeshInfo() mesh_info.set_points(points) mesh_info.set_facets(facets, facet_markers) generated_mesh = triangle.build(mesh_info, refinement_func=refine_func) from hedge.mesh import make_conformal_mesh return make_conformal_mesh( generated_mesh.points, generated_mesh.elements, boundary_tagger)
def make_mesh(): array = numpy.array # # 1---8---2 # |7 /|\ 1| # | / | \ | # |/ 6|0 \| # 5---4---7 # |\ 5|3 /| # | \ | / | # |4 \|/ 2| # 0---6---3 # points = [ array([-0.5, -0.5]), array([-0.5, 0.5]), array([0.5, 0.5]), array([0.5, -0.5]), array([0.0, 0.0]), array([-0.5, 0.0]), array([0.0, -0.5]), array([0.5, 0.0]), array([0.0, 0.5]) ] elements = [ [8, 7, 4], [8, 7, 2], [6, 7, 3], [7, 4, 6], [5, 6, 0], [5, 6, 4], [5, 8, 4], [1, 5, 8], ] def boundary_tagger(vertices, el, face_nr, all_v): if dot(el.face_normals[face_nr], v) < 0: return ["inflow"] else: return ["outflow"] from hedge.mesh import make_conformal_mesh return make_conformal_mesh(points, elements, boundary_tagger)
def make_mesh(): array = numpy.array # # 1---8---2 # |7 /|\ 1| # | / | \ | # |/ 6|0 \| # 5---4---7 # |\ 5|3 /| # | \ | / | # |4 \|/ 2| # 0---6---3 # points = [ array([-0.5, -0.5]), array([-0.5, 0.5]), array([0.5, 0.5]), array([0.5, -0.5]), array([0.0, 0.0]), array([-0.5, 0.0]), array([0.0, -0.5]), array([0.5, 0.0]), array([0.0, 0.5])] elements = [ [8, 7, 4], [8, 7, 2], [6, 7, 3], [7, 4, 6], [5, 6, 0], [5, 6, 4], [5, 8, 4], [1, 5, 8], ] def boundary_tagger(vertices, el, face_nr, all_v): if dot(el.face_normals[face_nr], v) < 0: return ["inflow"] else: return ["outflow"] from hedge.mesh import make_conformal_mesh return make_conformal_mesh(points, elements, boundary_tagger)
def make_mesh(a, b, pml_width=0.25, **kwargs): from meshpy.geometry import GeometryBuilder, make_box geob = GeometryBuilder() box_points, box_facets, _, box_markers = make_box(a, b) geob.add_geometry(box_points, box_facets) geob.wrap_in_box(pml_width) mesh_mod = geob.mesher_module() mi = mesh_mod.MeshInfo() geob.set(mi) built_mi = mesh_mod.build(mi, **kwargs) def boundary_tagger(fvi, el, fn, points): return [] from hedge.mesh import make_conformal_mesh return make_conformal_mesh( built_mi.points, built_mi.elements, boundary_tagger)
def make_regular_rect_mesh(a=(0, 0), b=(1, 1), n=(5, 5), periodicity=None, boundary_tagger=(lambda fvi, el, fn, all_v: [])): """Create a semi-structured rectangular mesh. :param a: the lower left hand point of the rectangle :param b: the upper right hand point of the rectangle :param n: a tuple of integers indicating the total number of points on [a,b]. :param periodicity: either None, or a tuple of bools specifying whether the mesh is to be periodic in x and y. """ if min(n) < 2: raise ValueError("need at least two points in each direction") node_dict = {} points = [] points_1d = [numpy.linspace(a_i, b_i, n_i) for a_i, b_i, n_i in zip(a, b, n)] for j in range(n[1]): for i in range(n[0]): node_dict[i, j] = len(points) points.append(numpy.array([points_1d[0][i], points_1d[1][j]])) elements = [] if periodicity is None: periodicity = (False, False) axes = ["x", "y"] mesh_periodicity = [] periodic_tags = set() for i, axis in enumerate(axes): if periodicity[i]: minus_tag = "minus_"+axis plus_tag = "plus_"+axis mesh_periodicity.append((minus_tag, plus_tag)) periodic_tags.add(minus_tag) periodic_tags.add(plus_tag) else: mesh_periodicity.append(None) fvi2fm = {} for i in range(n[0]-1): for j in range(n[1]-1): # c--d # | | # a--b a = node_dict[i, j] b = node_dict[i+1, j] c = node_dict[i, j+1] d = node_dict[i+1, j+1] elements.append((a, b, c)) elements.append((d, c, b)) if i == 0: fvi2fm[frozenset((a, c))] = "minus_x" if i == n[0]-2: fvi2fm[frozenset((b, d))] = "plus_x" if j == 0: fvi2fm[frozenset((a, b))] = "minus_y" if j == n[1]-2: fvi2fm[frozenset((c, d))] = "plus_y" def wrapped_boundary_tagger(fvi, el, fn, all_v): btag = fvi2fm[frozenset(fvi)] if btag in periodic_tags: return [btag] else: return [btag] + boundary_tagger(fvi, el, fn, all_v) from hedge.mesh import make_conformal_mesh return make_conformal_mesh(points, elements, wrapped_boundary_tagger, periodicity=mesh_periodicity)
def make_boxmesh(): from meshpy.tet import MeshInfo, build from meshpy.geometry import GeometryBuilder, Marker, make_box geob = GeometryBuilder() box_marker = Marker.FIRST_USER_MARKER extent_small = 0.1*numpy.ones(3, dtype=numpy.float64) geob.add_geometry(*make_box(-extent_small, extent_small)) # make small "separator box" for region attribute geob.add_geometry( *make_box( -extent_small*4, numpy.array([4, 0.4, 0.4], dtype=numpy.float64))) geob.add_geometry( *make_box( numpy.array([-1, -1, -1], dtype=numpy.float64), numpy.array([5, 1, 1], dtype=numpy.float64))) mesh_info = MeshInfo() geob.set(mesh_info) mesh_info.set_holes([(0, 0, 0)]) # region attributes mesh_info.regions.resize(1) mesh_info.regions[0] = ( # point in region list(extent_small*2) + [ # region number 1, # max volume in region #0.0001 0.005 ]) mesh = build(mesh_info, max_volume=0.02, volume_constraints=True, attributes=True) print "%d elements" % len(mesh.elements) #mesh.write_vtk("box-in-box.vtk") #print "done writing" fvi2fm = mesh.face_vertex_indices_to_face_marker face_marker_to_tag = { box_marker: "noslip", Marker.MINUS_X: "inflow", Marker.PLUS_X: "outflow", Marker.MINUS_Y: "inflow", Marker.PLUS_Y: "inflow", Marker.PLUS_Z: "inflow", Marker.MINUS_Z: "inflow" } def bdry_tagger(fvi, el, fn, all_v): face_marker = fvi2fm[fvi] return [face_marker_to_tag[face_marker]] from hedge.mesh import make_conformal_mesh return make_conformal_mesh( mesh.points, mesh.elements, bdry_tagger)
def make_wingmesh(): import numpy from math import pi, cos, sin from meshpy.tet import MeshInfo, build from meshpy.geometry import GeometryBuilder, Marker, \ generate_extrusion, make_box geob = GeometryBuilder() profile_marker = Marker.FIRST_USER_MARKER wing_length = 2 wing_subdiv = 5 rz_points = [ (0, -wing_length*1.05), (0.7, -wing_length*1.05), ] + [ (r, x) for x, r in zip( numpy.linspace(-wing_length, 0, wing_subdiv, endpoint=False), numpy.linspace(0.8, 1, wing_subdiv, endpoint=False)) ] + [(1,0)] + [ (r, x) for x, r in zip( numpy.linspace(wing_length, 0, wing_subdiv, endpoint=False), numpy.linspace(0.8, 1, wing_subdiv, endpoint=False)) ][::-1] + [ (0.7, wing_length*1.05), (0, wing_length*1.05) ] from meshpy.naca import get_naca_points geob.add_geometry(*generate_extrusion( rz_points=rz_points, base_shape=get_naca_points("0012", number_of_points=20), ring_markers=(wing_subdiv*2+4)*[profile_marker])) def deform_wing(p): x, y, z = p return numpy.array([ x + 0.8*abs(z/wing_length)** 1.2, y + 0.1*abs(z/wing_length)**2, z]) geob.apply_transform(deform_wing) points, facets, facet_markers = make_box( numpy.array([-1.5,-1,-wing_length-1], dtype=numpy.float64), numpy.array([3,1,wing_length+1], dtype=numpy.float64)) geob.add_geometry(points, facets, facet_markers=facet_markers) mesh_info = MeshInfo() geob.set(mesh_info) mesh_info.set_holes([(0.5,0,0)]) mesh = build(mesh_info) print "%d elements" % len(mesh.elements) fvi2fm = mesh.face_vertex_indices_to_face_marker face_marker_to_tag = { profile_marker: "noslip", Marker.MINUS_X: "inflow", Marker.PLUS_X: "outflow", Marker.MINUS_Y: "inflow", Marker.PLUS_Y: "inflow", Marker.PLUS_Z: "inflow", Marker.MINUS_Z: "inflow" } def bdry_tagger(fvi, el, fn, all_v): face_marker = fvi2fm[fvi] return [face_marker_to_tag[face_marker]] from hedge.mesh import make_conformal_mesh return make_conformal_mesh(mesh.points, mesh.elements, bdry_tagger)
def test_interior_fluxes_tet(): """Check tetrahedron surface integrals computed using interior fluxes against their known values. """ import meshpy.tet as tet from math import pi, sin, cos mesh_info = tet.MeshInfo() # construct a two-box extrusion of this base base = [(-pi, -pi, 0), (pi, -pi, 0), (pi, pi, 0), (-pi, pi, 0)] # first, the nodes mesh_info.set_points(base + [(x, y, z + pi) for x, y, z in base] + [(x, y, z + pi + 1) for x, y, z in base]) # next, the facets # vertex indices for a box missing the -z face box_without_minus_z = [ [4, 5, 6, 7], [0, 4, 5, 1], [1, 5, 6, 2], [2, 6, 7, 3], [3, 7, 4, 0], ] def add_to_all_vertex_indices(facets, increment): return [[pt + increment for pt in facet] for facet in facets] mesh_info.set_facets( [[0, 1, 2, 3]] # base + box_without_minus_z # first box + add_to_all_vertex_indices(box_without_minus_z, 4) # second box ) # set the volume properties -- this is where the tet size constraints are mesh_info.regions.resize(2) mesh_info.regions[0] = [ 0, 0, pi / 2, # point in volume -> first box 0, # region tag (user-defined number) 0.5, # max tet volume in region ] mesh_info.regions[1] = [ 0, 0, pi + 0.5, # point in volume -> second box 1, # region tag (user-defined number, arbitrary) 0.1, # max tet volume in region ] generated_mesh = tet.build(mesh_info, attributes=True, volume_constraints=True) from hedge.mesh import make_conformal_mesh mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements) from hedge.discretization.local import TetrahedronDiscretization from hedge.discretization import ones_on_volume discr = discr_class(mesh, TetrahedronDiscretization(4), debug=discr_class.noninteractive_debug_flags()) def f_u(x, el): if generated_mesh.element_attributes[el.id] == 1: return cos(x[0] - x[1] + x[2]) else: return 0 def f_l(x, el): if generated_mesh.element_attributes[el.id] == 0: return sin(x[0] - x[1] + x[2]) else: return 0 u_l = discr.interpolate_volume_function(f_l) u_u = discr.interpolate_volume_function(f_u) u = u_l + u_u # visualize the produced field #from hedge.visualization import SiloVisualizer #vis = SiloVisualizer(discr) #visf = vis.make_file("sandwich") #vis.add_data(visf, #[("u_l", u_l), ("u_u", u_u)], #expressions=[("u", "u_l+u_u")]) # make sure the surface integral of the difference # between top and bottom is zero from hedge.flux import make_normal, FluxScalarPlaceholder from hedge.optemplate import Field, get_flux_operator fluxu = FluxScalarPlaceholder() res = discr.compile( get_flux_operator( (fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u) ones = ones_on_volume(discr) assert abs(numpy.dot(res, ones)) < 5e-14
def partition_mesh(mesh, partition, part_bdry_tag_factory): """*partition* is a mapping that maps element id to integers that represent different pieces of the mesh. For historical reasons, the values in partition are called 'parts'. """ # Find parts to which we need to distribute. all_parts = list(set( partition[el.id] for el in mesh.elements)) # Prepare a mapping of elements to tags to speed up # copy_el_tagger, below. el2tags = {} for tag, elements in mesh.tag_to_elements.iteritems(): if tag == hedge.mesh.TAG_ALL: continue for el in elements: el2tags.setdefault(el, []).append(tag) # prepare a mapping of (el, face_nr) to boundary_tags # to speed up partition_bdry_tagger, below elface2tags = {} for tag, elfaces in mesh.tag_to_boundary.iteritems(): if tag == hedge.mesh.TAG_ALL: continue for el, fn in elfaces: elface2tags.setdefault((el, fn), []).append(tag) # prepare a mapping from (el, face_nr) to the part # at the other end of the interface, if different from # current. concurrently, prepare a mapping # part -> set([parts that border me]) elface2part = {} neighboring_parts = {} for elface1, elface2 in mesh.interfaces: e1, f1 = elface1 e2, f2 = elface2 r1 = partition[e1.id] r2 = partition[e2.id] if r1 != r2: neighboring_parts.setdefault(r1, set()).add(r2) neighboring_parts.setdefault(r2, set()).add(r1) elface2part[elface1] = r2 elface2part[elface2] = r1 # prepare a new mesh for each part and send it from hedge.mesh import TAG_NO_BOUNDARY for part in all_parts: part_global_elements = [el for el in mesh.elements if partition[el.id] == part] # pick out this part's vertices from pytools import flatten part_global_vertex_indices = set(flatten( el.vertex_indices for el in part_global_elements)) part_local_vertices = [mesh.points[vi] for vi in part_global_vertex_indices] # find global-to-local maps part_global2local_vertex_indices = dict( (gvi, lvi) for lvi, gvi in enumerate(part_global_vertex_indices)) part_global2local_elements = dict( (el.id, i) for i, el in enumerate(part_global_elements)) # find elements in local numbering part_local_elements = [ [part_global2local_vertex_indices[vi] for vi in el.vertex_indices] for el in part_global_elements] # make new local Mesh object, including # boundary and element tagging def partition_bdry_tagger(fvi, local_el, fn, all_vertices): el = part_global_elements[local_el.id] result = elface2tags.get((el, fn), []) try: opp_part = elface2part[el, fn] result.append(part_bdry_tag_factory(opp_part)) # keeps this part of the boundary from falling # under TAG_ALL. result.append(TAG_NO_BOUNDARY) except KeyError: pass return result def copy_el_tagger(local_el, all_vertices): return el2tags.get(part_global_elements[local_el.id], []) def is_partbdry_face((local_el, face_nr)): return (part_global_elements[local_el.id], face_nr) in elface2part from hedge.mesh import make_conformal_mesh part_mesh = make_conformal_mesh( part_local_vertices, part_local_elements, partition_bdry_tagger, copy_el_tagger, mesh.periodicity, is_partbdry_face) # assemble per-part data my_nb_parts = neighboring_parts.get(part, []) yield PartitionData( part, part_mesh, part_global2local_elements, part_global2local_vertex_indices, my_nb_parts, mesh.periodic_opposite_faces, part_boundary_tags=dict( (nb_part, part_bdry_tag_factory(nb_part)) for nb_part in my_nb_parts), tag_to_elements = part_mesh.tag_to_elements )
def partition_mesh(mesh, partition, part_bdry_tag_factory): """*partition* is a mapping that maps element id to integers that represent different pieces of the mesh. For historical reasons, the values in partition are called 'parts'. """ # Find parts to which we need to distribute. all_parts = list(set(partition[el.id] for el in mesh.elements)) # Prepare a mapping of elements to tags to speed up # copy_el_tagger, below. el2tags = {} for tag, elements in mesh.tag_to_elements.iteritems(): if tag == hedge.mesh.TAG_ALL: continue for el in elements: el2tags.setdefault(el, []).append(tag) # prepare a mapping of (el, face_nr) to boundary_tags # to speed up partition_bdry_tagger, below elface2tags = {} for tag, elfaces in mesh.tag_to_boundary.iteritems(): if tag == hedge.mesh.TAG_ALL: continue for el, fn in elfaces: elface2tags.setdefault((el, fn), []).append(tag) # prepare a mapping from (el, face_nr) to the part # at the other end of the interface, if different from # current. concurrently, prepare a mapping # part -> set([parts that border me]) elface2part = {} neighboring_parts = {} for elface1, elface2 in mesh.interfaces: e1, f1 = elface1 e2, f2 = elface2 r1 = partition[e1.id] r2 = partition[e2.id] if r1 != r2: neighboring_parts.setdefault(r1, set()).add(r2) neighboring_parts.setdefault(r2, set()).add(r1) elface2part[elface1] = r2 elface2part[elface2] = r1 # prepare a new mesh for each part and send it from hedge.mesh import TAG_NO_BOUNDARY for part in all_parts: part_global_elements = [ el for el in mesh.elements if partition[el.id] == part ] # pick out this part's vertices from pytools import flatten part_global_vertex_indices = set( flatten(el.vertex_indices for el in part_global_elements)) part_local_vertices = [ mesh.points[vi] for vi in part_global_vertex_indices ] # find global-to-local maps part_global2local_vertex_indices = dict( (gvi, lvi) for lvi, gvi in enumerate(part_global_vertex_indices)) part_global2local_elements = dict( (el.id, i) for i, el in enumerate(part_global_elements)) # find elements in local numbering part_local_elements = [[ part_global2local_vertex_indices[vi] for vi in el.vertex_indices ] for el in part_global_elements] # make new local Mesh object, including # boundary and element tagging def partition_bdry_tagger(fvi, local_el, fn, all_vertices): el = part_global_elements[local_el.id] result = elface2tags.get((el, fn), []) try: opp_part = elface2part[el, fn] result.append(part_bdry_tag_factory(opp_part)) # keeps this part of the boundary from falling # under TAG_ALL. result.append(TAG_NO_BOUNDARY) except KeyError: pass return result def copy_el_tagger(local_el, all_vertices): return el2tags.get(part_global_elements[local_el.id], []) def is_partbdry_face((local_el, face_nr)): return (part_global_elements[local_el.id], face_nr) in elface2part from hedge.mesh import make_conformal_mesh part_mesh = make_conformal_mesh(part_local_vertices, part_local_elements, partition_bdry_tagger, copy_el_tagger, mesh.periodicity, is_partbdry_face) # assemble per-part data my_nb_parts = neighboring_parts.get(part, []) yield PartitionData(part, part_mesh, part_global2local_elements, part_global2local_vertex_indices, my_nb_parts, mesh.periodic_opposite_faces, part_boundary_tags=dict( (nb_part, part_bdry_tag_factory(nb_part)) for nb_part in my_nb_parts), tag_to_elements=part_mesh.tag_to_elements)
def test_interior_fluxes_tet(): """Check tetrahedron surface integrals computed using interior fluxes against their known values. """ import meshpy.tet as tet from math import pi, sin, cos mesh_info = tet.MeshInfo() # construct a two-box extrusion of this base base = [(-pi, -pi, 0), (pi, -pi, 0), (pi, pi, 0), (-pi, pi, 0)] # first, the nodes mesh_info.set_points(base + [(x, y, z + pi) for x, y, z in base] + [(x, y, z + pi + 1) for x, y, z in base]) # next, the facets # vertex indices for a box missing the -z face box_without_minus_z = [[4, 5, 6, 7], [0, 4, 5, 1], [1, 5, 6, 2], [2, 6, 7, 3], [3, 7, 4, 0]] def add_to_all_vertex_indices(facets, increment): return [[pt + increment for pt in facet] for facet in facets] mesh_info.set_facets( [[0, 1, 2, 3]] # base + box_without_minus_z # first box + add_to_all_vertex_indices(box_without_minus_z, 4) # second box ) # set the volume properties -- this is where the tet size constraints are mesh_info.regions.resize(2) mesh_info.regions[0] = [ 0, 0, pi / 2, # point in volume -> first box 0, # region tag (user-defined number) 0.5, # max tet volume in region ] mesh_info.regions[1] = [ 0, 0, pi + 0.5, # point in volume -> second box 1, # region tag (user-defined number, arbitrary) 0.1, # max tet volume in region ] generated_mesh = tet.build(mesh_info, attributes=True, volume_constraints=True) from hedge.mesh import make_conformal_mesh mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements) from hedge.discretization.local import TetrahedronDiscretization from hedge.discretization import ones_on_volume discr = discr_class(mesh, TetrahedronDiscretization(4), debug=discr_class.noninteractive_debug_flags()) def f_u(x, el): if generated_mesh.element_attributes[el.id] == 1: return cos(x[0] - x[1] + x[2]) else: return 0 def f_l(x, el): if generated_mesh.element_attributes[el.id] == 0: return sin(x[0] - x[1] + x[2]) else: return 0 u_l = discr.interpolate_volume_function(f_l) u_u = discr.interpolate_volume_function(f_u) u = u_l + u_u # visualize the produced field # from hedge.visualization import SiloVisualizer # vis = SiloVisualizer(discr) # visf = vis.make_file("sandwich") # vis.add_data(visf, # [("u_l", u_l), ("u_u", u_u)], # expressions=[("u", "u_l+u_u")]) # make sure the surface integral of the difference # between top and bottom is zero from hedge.flux import make_normal, FluxScalarPlaceholder from hedge.optemplate import Field, get_flux_operator fluxu = FluxScalarPlaceholder() res = discr.compile(get_flux_operator((fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u) from hedge.discretization import ones_on_volume ones = ones_on_volume(discr) assert abs(numpy.dot(res, ones)) < 5e-14
def test_interior_fluxes_tri(): """Check triangle surface integrals computed using interior fluxes against their known values. """ from math import pi, sin, cos def round_trip_connect(start, end): for i in range(start, end): yield i, i + 1 yield end, start a = -pi b = pi points = [(a, 0), (b, 0), (a, -1), (b, -1), (a, 1), (b, 1)] import meshpy.triangle as triangle mesh_info = triangle.MeshInfo() mesh_info.set_points(points) mesh_info.set_facets([(0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5), (1, 5)]) mesh_info.regions.resize(2) mesh_info.regions[0] = [0, -0.5, 1, 0.1] # coordinate # lower element tag # max area mesh_info.regions[1] = [0, 0.5, 2, 0.01] # coordinate # upper element tag # max area generated_mesh = triangle.build(mesh_info, attributes=True, volume_constraints=True) # triangle.write_gnuplot_mesh("mesh.dat", generated_mesh) def element_tagger(el): if generated_mesh.element_attributes[el.id] == 1: return ["upper"] else: return ["lower"] from hedge.mesh import make_conformal_mesh mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements) from hedge.discretization.local import TriangleDiscretization from hedge.discretization import ones_on_volume discr = discr_class(mesh, TriangleDiscretization(4), debug=discr_class.noninteractive_debug_flags()) def f_u(x, el): if generated_mesh.element_attributes[el.id] == 1: return cos(x[0] - x[1]) else: return 0 def f_l(x, el): if generated_mesh.element_attributes[el.id] == 0: return sin(x[0] - x[1]) else: return 0 u_l = discr.interpolate_volume_function(f_l) u_u = discr.interpolate_volume_function(f_u) u = u_u + u_u # discr.visualize_vtk("dual.vtk", [("u", u)]) from hedge.flux import make_normal, FluxScalarPlaceholder from hedge.optemplate import Field, get_flux_operator fluxu = FluxScalarPlaceholder() res = discr.compile(get_flux_operator((fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u) from hedge.discretization import ones_on_volume ones = ones_on_volume(discr) err = abs(numpy.dot(res, ones)) # print err assert err < 5e-14
def make_boxmesh(): from meshpy.tet import MeshInfo, build from meshpy.geometry import GeometryBuilder, Marker, make_box geob = GeometryBuilder() box_marker = Marker.FIRST_USER_MARKER extent_small = 0.1 * numpy.ones(3, dtype=numpy.float64) geob.add_geometry(*make_box(-extent_small, extent_small)) # make small "separator box" for region attribute geob.add_geometry( *make_box(-extent_small * 4, numpy.array([4, 0.4, 0.4], dtype=numpy.float64))) geob.add_geometry(*make_box(numpy.array([-1, -1, -1], dtype=numpy.float64), numpy.array([5, 1, 1], dtype=numpy.float64))) mesh_info = MeshInfo() geob.set(mesh_info) mesh_info.set_holes([(0, 0, 0)]) # region attributes mesh_info.regions.resize(1) mesh_info.regions[0] = ( # point in region list(extent_small * 2) + [ # region number 1, # max volume in region #0.0001 0.005 ]) mesh = build(mesh_info, max_volume=0.02, volume_constraints=True, attributes=True) print "%d elements" % len(mesh.elements) #mesh.write_vtk("box-in-box.vtk") #print "done writing" fvi2fm = mesh.face_vertex_indices_to_face_marker face_marker_to_tag = { box_marker: "noslip", Marker.MINUS_X: "inflow", Marker.PLUS_X: "outflow", Marker.MINUS_Y: "inflow", Marker.PLUS_Y: "inflow", Marker.PLUS_Z: "inflow", Marker.MINUS_Z: "inflow" } def bdry_tagger(fvi, el, fn, all_v): face_marker = fvi2fm[fvi] return [face_marker_to_tag[face_marker]] from hedge.mesh import make_conformal_mesh return make_conformal_mesh(mesh.points, mesh.elements, bdry_tagger)
def test_interior_fluxes_tri(): """Check triangle surface integrals computed using interior fluxes against their known values. """ from math import pi, sin, cos def round_trip_connect(start, end): for i in range(start, end): yield i, i + 1 yield end, start a = -pi b = pi points = [(a, 0), (b, 0), (a, -1), (b, -1), (a, 1), (b, 1)] import meshpy.triangle as triangle mesh_info = triangle.MeshInfo() mesh_info.set_points(points) mesh_info.set_facets([(0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5), (1, 5)]) mesh_info.regions.resize(2) mesh_info.regions[0] = [ 0, -0.5, # coordinate 1, # lower element tag 0.1, # max area ] mesh_info.regions[1] = [ 0, 0.5, # coordinate 2, # upper element tag 0.01, # max area ] generated_mesh = triangle.build(mesh_info, attributes=True, volume_constraints=True) #triangle.write_gnuplot_mesh("mesh.dat", generated_mesh) def element_tagger(el): if generated_mesh.element_attributes[el.id] == 1: return ["upper"] else: return ["lower"] from hedge.mesh import make_conformal_mesh mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements) from hedge.discretization.local import TriangleDiscretization from hedge.discretization import ones_on_volume discr = discr_class(mesh, TriangleDiscretization(4), debug=discr_class.noninteractive_debug_flags()) def f_u(x, el): if generated_mesh.element_attributes[el.id] == 1: return cos(x[0] - x[1]) else: return 0 def f_l(x, el): if generated_mesh.element_attributes[el.id] == 0: return sin(x[0] - x[1]) else: return 0 # u_l = discr.interpolate_volume_function(f_l) u_u = discr.interpolate_volume_function(f_u) u = u_u + u_u #discr.visualize_vtk("dual.vtk", [("u", u)]) from hedge.flux import make_normal, FluxScalarPlaceholder from hedge.optemplate import Field, get_flux_operator fluxu = FluxScalarPlaceholder() res = discr.compile( get_flux_operator( (fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u) ones = ones_on_volume(discr) err = abs(numpy.dot(res, ones)) #print err assert err < 5e-14
def make_wingmesh(): import numpy from math import pi, cos, sin from meshpy.tet import MeshInfo, build from meshpy.geometry import GeometryBuilder, Marker, \ generate_extrusion, make_box geob = GeometryBuilder() profile_marker = Marker.FIRST_USER_MARKER wing_length = 2 wing_subdiv = 5 rz_points = [ (0, -wing_length * 1.05), (0.7, -wing_length * 1.05), ] + [(r, x) for x, r in zip( numpy.linspace(-wing_length, 0, wing_subdiv, endpoint=False), numpy.linspace(0.8, 1, wing_subdiv, endpoint=False))] + [(1, 0)] + [ (r, x) for x, r in zip( numpy.linspace(wing_length, 0, wing_subdiv, endpoint=False), numpy.linspace(0.8, 1, wing_subdiv, endpoint=False)) ][::-1] + [(0.7, wing_length * 1.05), (0, wing_length * 1.05)] from meshpy.naca import get_naca_points geob.add_geometry(*generate_extrusion( rz_points=rz_points, base_shape=get_naca_points("0012", number_of_points=20), ring_markers=(wing_subdiv * 2 + 4) * [profile_marker])) def deform_wing(p): x, y, z = p return numpy.array([ x + 0.8 * abs(z / wing_length)**1.2, y + 0.1 * abs(z / wing_length)**2, z ]) geob.apply_transform(deform_wing) points, facets, facet_markers = make_box( numpy.array([-1.5, -1, -wing_length - 1], dtype=numpy.float64), numpy.array([3, 1, wing_length + 1], dtype=numpy.float64)) geob.add_geometry(points, facets, facet_markers=facet_markers) mesh_info = MeshInfo() geob.set(mesh_info) mesh_info.set_holes([(0.5, 0, 0)]) mesh = build(mesh_info) print "%d elements" % len(mesh.elements) fvi2fm = mesh.face_vertex_indices_to_face_marker face_marker_to_tag = { profile_marker: "noslip", Marker.MINUS_X: "inflow", Marker.PLUS_X: "outflow", Marker.MINUS_Y: "inflow", Marker.PLUS_Y: "inflow", Marker.PLUS_Z: "inflow", Marker.MINUS_Z: "inflow" } def bdry_tagger(fvi, el, fn, all_v): face_marker = fvi2fm[fvi] return [face_marker_to_tag[face_marker]] from hedge.mesh import make_conformal_mesh return make_conformal_mesh(mesh.points, mesh.elements, bdry_tagger)