def quadrature_rule(self): dims = self.mesh_el_group.dim if dims == 0: return mp.ZeroDimensionalQuadrature() elif dims == 1: return mp.LegendreGaussQuadrature(self.order) else: return mp.VioreanuRokhlinSimplexQuadrature(self.order, dims)
def _quadrature_rule(self): dims = self.mesh_el_group.dim if dims == 0: return mp.Quadrature(np.empty((0, 1)), np.empty((0, 1))) elif dims == 1: return mp.LegendreGaussQuadrature(self.order) else: return mp.VioreanuRokhlinSimplexQuadrature(self.order, dims)
def test_mesh_with_interior_unit_nodes(actx_factory, ambient_dim): actx = actx_factory() # NOTE: smaller orders or coarser meshes make the cases fail the # node_vertex_consistency test; the default warp_and_blend_nodes have # nodes at the vertices, so they pass for much smaller tolerances order = 8 nelements = 32 n_minor = 2 * nelements uniform_refinement_rounds = 4 import modepy as mp if ambient_dim == 2: unit_nodes = mp.LegendreGaussQuadrature(order, force_dim_axis=True).nodes mesh = mgen.make_curve_mesh(partial(mgen.ellipse, 2.0), np.linspace(0.0, 1.0, nelements + 1), order=order, unit_nodes=unit_nodes) elif ambient_dim == 3: unit_nodes = mp.VioreanuRokhlinSimplexQuadrature(order, 2).nodes mesh = mgen.generate_torus(4.0, 2.0, n_major=2 * n_minor, n_minor=n_minor, order=order, unit_nodes=unit_nodes) mesh = mgen.generate_icosphere( 1.0, uniform_refinement_rounds=uniform_refinement_rounds, order=order, unit_nodes=unit_nodes) else: raise ValueError(f"unsupported dimension: '{ambient_dim}'") assert mesh.facial_adjacency_groups assert mesh.nodal_adjacency from meshmode.discretization import Discretization from meshmode.discretization.poly_element import QuadratureSimplexGroupFactory discr = Discretization(actx, mesh, QuadratureSimplexGroupFactory(order)) from meshmode.discretization.connection import make_face_restriction conn = make_face_restriction( actx, discr, group_factory=QuadratureSimplexGroupFactory(order), boundary_tag=FACE_RESTR_ALL) assert conn
def run(actx, *, ambient_dim: int = 3, resolution: int = None, target_order: int = 4, tmax: float = 1.0, timestep: float = 1.0e-2, group_factory_name: str = "warp_and_blend", visualize: bool = True): if ambient_dim not in (2, 3): raise ValueError(f"unsupported dimension: {ambient_dim}") mesh_order = target_order radius = 1.0 # {{{ geometry # {{{ element groups import modepy as mp import meshmode.discretization.poly_element as poly # NOTE: picking the same unit nodes for the mesh and the discr saves # a bit of work when reconstructing after a time step if group_factory_name == "warp_and_blend": group_factory_cls = poly.PolynomialWarpAndBlendGroupFactory unit_nodes = mp.warp_and_blend_nodes(ambient_dim - 1, mesh_order) elif group_factory_name == "quadrature": group_factory_cls = poly.InterpolatoryQuadratureSimplexGroupFactory if ambient_dim == 2: unit_nodes = mp.LegendreGaussQuadrature( mesh_order, force_dim_axis=True).nodes else: unit_nodes = mp.VioreanuRokhlinSimplexQuadrature(mesh_order, 2).nodes else: raise ValueError(f"unknown group factory: '{group_factory_name}'") # }}} # {{{ discretization import meshmode.mesh.generation as gen if ambient_dim == 2: nelements = 8192 if resolution is None else resolution mesh = gen.make_curve_mesh( lambda t: radius * gen.ellipse(1.0, t), np.linspace(0.0, 1.0, nelements + 1), order=mesh_order, unit_nodes=unit_nodes) else: nrounds = 4 if resolution is None else resolution mesh = gen.generate_icosphere(radius, uniform_refinement_rounds=nrounds, order=mesh_order, unit_nodes=unit_nodes) from meshmode.discretization import Discretization discr0 = Discretization(actx, mesh, group_factory_cls(target_order)) logger.info("ndofs: %d", discr0.ndofs) logger.info("nelements: %d", discr0.mesh.nelements) # }}} if visualize: from meshmode.discretization.visualization import make_visualizer vis = make_visualizer(actx, discr0, vis_order=target_order, # NOTE: setting this to True will add some unnecessary # resampling in Discretization.nodes for the vis_discr underneath force_equidistant=False) # }}} # {{{ ode def velocity_field(nodes, alpha=1.0): return make_obj_array([ alpha * nodes[0], -alpha * nodes[1], 0.0 * nodes[0] ][:ambient_dim]) def source(t, x): discr = reconstruct_discr_from_nodes(actx, discr0, x) u = velocity_field(thaw(discr.nodes(), actx)) # {{{ # NOTE: these are just here because this was at some point used to # profile some more operators (turned out well!) from meshmode.discretization import num_reference_derivative x = thaw(discr.nodes()[0], actx) gradx = sum( num_reference_derivative(discr, (i,), x) for i in range(discr.dim)) intx = sum(actx.np.sum(xi * wi) for xi, wi in zip(x, discr.quad_weights())) assert gradx is not None assert intx is not None # }}} return u # }}} # {{{ evolve maxiter = int(tmax // timestep) + 1 dt = tmax / maxiter + 1.0e-15 x = thaw(discr0.nodes(), actx) t = 0.0 if visualize: filename = f"moving-geometry-{0:09d}.vtu" plot_solution(actx, vis, filename, discr0, t, x) for n in range(1, maxiter + 1): x = advance(actx, dt, t, x, source) t += dt if visualize: discr = reconstruct_discr_from_nodes(actx, discr0, x) vis = make_visualizer(actx, discr, vis_order=target_order) # vis = vis.copy_with_same_connectivity(actx, discr) filename = f"moving-geometry-{n:09d}.vtu" plot_solution(actx, vis, filename, discr, t, x) logger.info("[%05d/%05d] t = %.5e/%.5e dt = %.5e", n, maxiter, t, tmax, dt)