def _build_qbx_discr(queue, ndim=2, nelements=30, target_order=7, qbx_order=4, curve_f=None): if curve_f is None: curve_f = NArmedStarfish(5, 0.25) if ndim == 2: mesh = make_curve_mesh(curve_f, np.linspace(0, 1, nelements + 1), target_order) elif ndim == 3: mesh = generate_torus(10.0, 2.0, order=target_order) else: raise ValueError("unsupported ambient dimension") from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory from pytential.qbx import QBXLayerPotentialSource density_discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) qbx, _ = QBXLayerPotentialSource(density_discr, fine_order=4 * target_order, qbx_order=qbx_order, fmm_order=False).with_refinement() return qbx
def test_tangential_onb(ctx_factory): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import generate_torus mesh = generate_torus(5, 2, order=3) discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(3)) tob = sym.tangential_onb(mesh.ambient_dim) nvecs = tob.shape[1] # make sure tangential_onb is mutually orthogonal and normalized orth_check = bind(discr, sym.make_obj_array([ np.dot(tob[:, i], tob[:, j]) - (1 if i == j else 0) for i in range(nvecs) for j in range(nvecs)]) )(queue) for i, orth_i in enumerate(orth_check): assert (cl.clmath.fabs(orth_i) < 1e-13).get().all() # make sure tangential_onb is orthogonal to normal orth_check = bind(discr, sym.make_obj_array([ np.dot(tob[:, i], sym.normal(mesh.ambient_dim).as_vector()) for i in range(nvecs)]) )(queue) for i, orth_i in enumerate(orth_check): assert (cl.clmath.fabs(orth_i) < 1e-13).get().all()
def test_vtk_overwrite(ctx_getter): pytest.importorskip("pyvisfile") def _try_write_vtk(writer, obj): import os from meshmode import FileExistsError filename = "test_vtk_overwrite.vtu" if os.path.exists(filename): os.remove(filename) writer(filename, []) with pytest.raises(FileExistsError): writer(filename, []) writer(filename, [], overwrite=True) if os.path.exists(filename): os.remove(filename) ctx = ctx_getter() queue = cl.CommandQueue(ctx) target_order = 7 from meshmode.mesh.generation import generate_torus mesh = generate_torus(10.0, 2.0, order=target_order) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) from meshmode.discretization.visualization import make_visualizer from meshmode.discretization.visualization import \ write_nodal_adjacency_vtk_file from meshmode.mesh.visualization import write_vertex_vtk_file vis = make_visualizer(queue, discr, 1) _try_write_vtk(vis.write_vtk_file, discr) _try_write_vtk( lambda x, y, **kwargs: write_vertex_vtk_file(discr.mesh, x, **kwargs), discr.mesh) _try_write_vtk( lambda x, y, **kwargs: write_nodal_adjacency_vtk_file( x, discr.mesh, **kwargs), discr.mesh)
def test_vtk_overwrite(ctx_getter): pytest.importorskip("pyvisfile") def _try_write_vtk(writer, obj): import os from meshmode import FileExistsError filename = "test_vtk_overwrite.vtu" if os.path.exists(filename): os.remove(filename) writer(filename, []) with pytest.raises(FileExistsError): writer(filename, []) writer(filename, [], overwrite=True) if os.path.exists(filename): os.remove(filename) ctx = ctx_getter() queue = cl.CommandQueue(ctx) target_order = 7 from meshmode.mesh.generation import generate_torus mesh = generate_torus(10.0, 2.0, order=target_order) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) from meshmode.discretization.visualization import make_visualizer from meshmode.discretization.visualization import \ write_nodal_adjacency_vtk_file from meshmode.mesh.visualization import write_vertex_vtk_file vis = make_visualizer(queue, discr, 1) _try_write_vtk(vis.write_vtk_file, discr) _try_write_vtk(lambda x, y, **kwargs: write_vertex_vtk_file(discr.mesh, x, **kwargs), discr.mesh) _try_write_vtk(lambda x, y, **kwargs: write_nodal_adjacency_vtk_file(x, discr.mesh, **kwargs), discr.mesh)
def create_discretization(queue, ndim, nelements=42, mesh_name=None, order=4): ctx = queue.context # construct mesh if ndim == 2: from functools import partial from meshmode.mesh.generation import make_curve_mesh, ellipse, starfish if mesh_name is None: mesh_name = "ellipse" t = np.linspace(0.0, 1.0, nelements + 1) if mesh_name == "ellipse": mesh = make_curve_mesh(partial(ellipse, 2), t, order=order) elif mesh_name == "starfish": mesh = make_curve_mesh(starfish, t, order=order) else: raise ValueError('unknown mesh name: {}'.format(mesh_name)) elif ndim == 3: from meshmode.mesh.generation import generate_torus from meshmode.mesh.generation import generate_warped_rect_mesh if mesh_name is None: mesh_name = "torus" if mesh_name == "torus": mesh = generate_torus(10.0, 5.0, order=order, n_minor=nelements, n_major=nelements) elif mesh_name == "warp": mesh = generate_warped_rect_mesh(ndim, order=order, n=nelements) else: raise ValueError("unknown mesh name: {}".format(mesh_name)) else: raise ValueError("unsupported dimension: {}".format(ndim)) # create discretization from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory discr = Discretization(ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(order)) return discr
def create_discretization(queue, ndim, nelements=42, mesh_name=None, order=4): ctx = queue.context # construct mesh if ndim == 2: from functools import partial from meshmode.mesh.generation import make_curve_mesh, ellipse, starfish if mesh_name is None: mesh_name = "ellipse" t = np.linspace(0.0, 1.0, nelements + 1) if mesh_name == "ellipse": mesh = make_curve_mesh(partial(ellipse, 2), t, order=order) elif mesh_name == "starfish": mesh = make_curve_mesh(starfish, t, order=order) else: raise ValueError('unknown mesh name: {}'.format(mesh_name)) elif ndim == 3: from meshmode.mesh.generation import generate_torus from meshmode.mesh.generation import generate_warped_rect_mesh if mesh_name is None: mesh_name = "torus" if mesh_name == "torus": mesh = generate_torus(10.0, 5.0, order=order, n_inner=nelements, n_outer=nelements) elif mesh_name == "warp": mesh = generate_warped_rect_mesh(ndim, order=order, n=nelements) else: raise ValueError("unknown mesh name: {}".format(mesh_name)) else: raise ValueError("unsupported dimension: {}".format(ndim)) # create discretization from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory discr = Discretization(ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(order)) return discr
def test_is_affine_group_check(mesh_name): order = 4 nelements = 16 if mesh_name.startswith("box"): dim = int(mesh_name[-2]) is_affine = True mesh = mgen.generate_regular_rect_mesh( a=(-0.5, ) * dim, b=(0.5, ) * dim, nelements_per_axis=(nelements, ) * dim, order=order) elif mesh_name.startswith("warped_box"): dim = int(mesh_name[-2]) is_affine = False mesh = mgen.generate_warped_rect_mesh(dim, order, nelements_side=nelements) elif mesh_name == "cross_warped_box": dim = 2 is_affine = False mesh = _generate_cross_warped_rect_mesh(dim, order, nelements) elif mesh_name == "circle": is_affine = False mesh = mgen.make_curve_mesh(lambda t: mgen.ellipse(1.0, t), np.linspace(0.0, 1.0, nelements + 1), order=order) elif mesh_name == "ellipse": is_affine = False mesh = mgen.make_curve_mesh(lambda t: mgen.ellipse(2.0, t), np.linspace(0.0, 1.0, nelements + 1), order=order) elif mesh_name == "sphere": is_affine = False mesh = mgen.generate_icosphere(r=1.0, order=order) elif mesh_name == "torus": is_affine = False mesh = mgen.generate_torus(10.0, 2.0, order=order) else: raise ValueError(f"unknown mesh name: {mesh_name}") assert all(grp.is_affine for grp in mesh.groups) == is_affine
def test_vtk_overwrite(actx_factory): pytest.importorskip("pyvisfile") def _try_write_vtk(writer, obj): import os filename = "vtk_overwrite_temp.vtu" if os.path.exists(filename): os.remove(filename) writer(filename, []) with pytest.raises(FileExistsError): writer(filename, []) writer(filename, [], overwrite=True) if os.path.exists(filename): os.remove(filename) actx = actx_factory() target_order = 7 mesh = mgen.generate_torus(10.0, 2.0, order=target_order) from meshmode.discretization import Discretization discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) from meshmode.discretization.visualization import make_visualizer from meshmode.discretization.visualization import \ write_nodal_adjacency_vtk_file from meshmode.mesh.visualization import write_vertex_vtk_file vis = make_visualizer(actx, discr, 1) _try_write_vtk(vis.write_vtk_file, discr) _try_write_vtk( lambda x, y, **kwargs: write_vertex_vtk_file(discr.mesh, x, **kwargs), discr.mesh) _try_write_vtk( lambda x, y, **kwargs: write_nodal_adjacency_vtk_file( x, discr.mesh, **kwargs), discr.mesh)
def test_refine_surfaces(actx_factory, mesh_name, visualize=False): if mesh_name == "torus": mesh = mgen.generate_torus(10, 1, 40, 4, order=4) elif mesh_name == "icosphere": mesh = mgen.generate_icosphere(1, order=4) else: raise ValueError(f"invalid mesh name '{mesh_name}'") if visualize: actx = actx_factory() from meshmode.mesh.visualization import vtk_visualize_mesh vtk_visualize_mesh(actx, mesh, "surface.vtu") # check for absence of node-vertex consistency error from meshmode.mesh.refinement import refine_uniformly refined_mesh = refine_uniformly(mesh, 1) if visualize: actx = actx_factory() from meshmode.mesh.visualization import vtk_visualize_mesh vtk_visualize_mesh(actx, refined_mesh, "surface-refined.vtu")
def test_tangential_onb(ctx_factory): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) from meshmode.mesh.generation import generate_torus mesh = generate_torus(5, 2, order=3) discr = Discretization(actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(3)) tob = sym.tangential_onb(mesh.ambient_dim) nvecs = tob.shape[1] # make sure tangential_onb is mutually orthogonal and normalized orth_check = bind( discr, sym.make_obj_array([ np.dot(tob[:, i], tob[:, j]) - (1 if i == j else 0) for i in range(nvecs) for j in range(nvecs) ]))(actx) from meshmode.dof_array import flatten orth_check = flatten(orth_check) for i, orth_i in enumerate(orth_check): assert (cl.clmath.fabs(orth_i) < 1e-13).get().all() # make sure tangential_onb is orthogonal to normal orth_check = bind( discr, sym.make_obj_array([ np.dot(tob[:, i], sym.normal(mesh.ambient_dim).as_vector()) for i in range(nvecs) ]))(actx) orth_check = flatten(orth_check) for i, orth_i in enumerate(orth_check): assert (cl.clmath.fabs(orth_i) < 1e-13).get().all()
def get_lpot_source(queue, dim): from meshmode.discretization import Discretization from meshmode.discretization.poly_element import ( InterpolatoryQuadratureSimplexGroupFactory) target_order = TARGET_ORDER if dim == 2: from meshmode.mesh.generation import starfish, make_curve_mesh mesh = make_curve_mesh(starfish, np.linspace(0, 1, 50), order=target_order) elif dim == 3: from meshmode.mesh.generation import generate_torus mesh = generate_torus(2, 1, order=target_order) else: raise ValueError("unsupported dimension: %d" % dim) pre_density_discr = Discretization( queue.context, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) lpot_kwargs = DEFAULT_LPOT_KWARGS.copy() lpot_kwargs.update( _expansion_stick_out_factor=TCF, fmm_order=FMM_ORDER, qbx_order=QBX_ORDER, fmm_backend="fmmlib", ) from pytential.qbx import QBXLayerPotentialSource lpot_source = QBXLayerPotentialSource(pre_density_discr, OVSMP_FACTOR * target_order, **lpot_kwargs) lpot_source, _ = lpot_source.with_refinement() return lpot_source
def get_torus_with_ref_mean_curvature(cl_ctx, h): order = 4 r_minor = 1.0 r_major = 3.0 from meshmode.mesh.generation import generate_torus mesh = generate_torus(r_major, r_minor, n_major=h, n_minor=h, order=order) discr = Discretization(cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(order)) with cl.CommandQueue(cl_ctx) as queue: nodes = discr.nodes().get(queue=queue) # copied from meshmode.mesh.generation.generate_torus a = r_major b = r_minor u = np.arctan2(nodes[1], nodes[0]) rvec = np.array([np.cos(u), np.sin(u), np.zeros_like(u)]) rvec = np.sum(nodes * rvec, axis=0) - a cosv = np.cos(np.arctan2(nodes[2], rvec)) return discr, (a + 2.0 * b * cosv) / (2 * b * (a + b * cosv))
def get_torus_with_ref_mean_curvature(actx, h): order = 4 r_minor = 1.0 r_major = 3.0 from meshmode.mesh.generation import generate_torus mesh = generate_torus(r_major, r_minor, n_major=h, n_minor=h, order=order) discr = Discretization(actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(order)) from meshmode.dof_array import thaw nodes = thaw(actx, discr.nodes()) # copied from meshmode.mesh.generation.generate_torus a = r_major b = r_minor u = actx.np.arctan2(nodes[1], nodes[0]) from pytools.obj_array import flat_obj_array rvec = flat_obj_array(actx.np.cos(u), actx.np.sin(u), 0 * u) rvec = sum(nodes * rvec) - a cosv = actx.np.cos(actx.np.arctan2(nodes[2], rvec)) return discr, (a + 2.0 * b * cosv) / (2 * b * (a + b * cosv))
def main(): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import generate_torus rout = 10 rin = 1 if 1: base_mesh = generate_torus(rout, rin, 40, 4, mesh_order) from meshmode.mesh.processing import affine_map, merge_disjoint_meshes # nx = 1 # ny = 1 nz = 1 dz = 0 meshes = [ affine_map(base_mesh, A=np.diag([1, 1, 1]), b=np.array([0, 0, iz * dz])) for iz in range(nz) ] mesh = merge_disjoint_meshes(meshes, single_group=True) if 0: from meshmode.mesh.visualization import draw_curve draw_curve(mesh) import matplotlib.pyplot as plt plt.show() pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import (QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order, ).with_refinement() density_discr = qbx.density_discr # {{{ describe bvp from sumpy.kernel import LaplaceKernel kernel = LaplaceKernel(3) cse = sym.cse sigma_sym = sym.var("sigma") #sqrt_w = sym.sqrt_jac_q_weight(3) sqrt_w = 1 inv_sqrt_w_sigma = cse(sigma_sym / sqrt_w) # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = ( loc_sign * 0.5 * sigma_sym + sqrt_w * (sym.S(kernel, inv_sqrt_w_sigma) + sym.D(kernel, inv_sqrt_w_sigma))) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve nodes = density_discr.nodes().with_queue(queue) source = np.array([rout, 0, 0]) def u_incoming_func(x): # return 1/cl.clmath.sqrt( (x[0] - source[0])**2 # +(x[1] - source[1])**2 # +(x[2] - source[2])**2 ) return 1.0 / la.norm(x.get() - source[:, None], axis=0) bc = cl.array.to_device(queue, u_incoming_func(nodes)) bvp_rhs = bind(qbx, sqrt_w * sym.var("bc"))(queue, bc=bc) from pytential.solve import gmres gmres_result = gmres(bound_op.scipy_op(queue, "sigma", dtype=np.float64), bvp_rhs, tol=1e-14, progress=True, stall_iterations=0, hard_failure=True) sigma = bind(qbx, sym.var("sigma") / sqrt_w)(queue, sigma=gmres_result.solution) # }}} from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, 20) bdry_vis.write_vtk_file("laplace.vtu", [ ("sigma", sigma), ]) # {{{ postprocess/visualize repr_kwargs = dict(qbx_forced_limit=None) representation_sym = (sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) + sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs)) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(3), extent=20, npoints=50) targets = cl.array.to_device(queue, fplot.points) qbx_stick_out = qbx.copy(target_stick_out_factor=0.2) try: fld_in_vol = bind((qbx_stick_out, PointsTarget(targets)), representation_sym)(queue, sigma=sigma).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file("failed-targets.vts", [("failed", e.failed_target_flags.get(queue))]) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("potential-laplace-3d.vts", [ ("potential", fld_in_vol), ])
def get_mesh(self, resolution, mesh_order): from meshmode.mesh.generation import generate_torus mesh = generate_torus(self.r_major, self.r_minor, order=mesh_order) from meshmode.mesh.refinement import refine_uniformly return refine_uniformly(mesh, resolution)
def test_3d_jump_relations(ctx_factory, relation, visualize=False): # logging.basicConfig(level=logging.INFO) cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) if relation == "div_s": target_order = 3 else: target_order = 4 qbx_order = target_order from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for nel_factor in [6, 10, 14]: from meshmode.mesh.generation import generate_torus mesh = generate_torus( 5, 2, order=target_order, n_outer=2*nel_factor, n_inner=nel_factor) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory pre_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(3)) from pytential.qbx import QBXLayerPotentialSource qbx, _ = QBXLayerPotentialSource( pre_discr, fine_order=4*target_order, qbx_order=qbx_order, fmm_order=qbx_order + 5, fmm_backend="fmmlib" ).with_refinement() from sumpy.kernel import LaplaceKernel knl = LaplaceKernel(3) def nxcurlS(qbx_forced_limit): return sym.n_cross(sym.curl(sym.S( knl, sym.cse(sym.tangential_to_xyz(density_sym), "jxyz"), qbx_forced_limit=qbx_forced_limit))) x, y, z = qbx.density_discr.nodes().with_queue(queue) m = cl.clmath if relation == "nxcurls": density_sym = sym.make_sym_vector("density", 2) jump_identity_sym = ( nxcurlS(+1) - (nxcurlS("avg") + 0.5*sym.tangential_to_xyz(density_sym))) # The tangential coordinate system is element-local, so we can't just # conjure up some globally smooth functions, interpret their values # in the tangential coordinate system, and be done. Instead, generate # an XYZ function and project it. density = bind( qbx, sym.xyz_to_tangential(sym.make_sym_vector("jxyz", 3)))( queue, jxyz=sym.make_obj_array([ m.cos(0.5*x) * m.cos(0.5*y) * m.cos(0.5*z), m.sin(0.5*x) * m.cos(0.5*y) * m.sin(0.5*z), m.sin(0.5*x) * m.cos(0.5*y) * m.cos(0.5*z), ])) elif relation == "sp": density = m.cos(2*x) * m.cos(2*y) * m.cos(z) density_sym = sym.var("density") jump_identity_sym = ( sym.Sp(knl, density_sym, qbx_forced_limit=+1) - (sym.Sp(knl, density_sym, qbx_forced_limit="avg") - 0.5*density_sym)) elif relation == "div_s": density = m.cos(2*x) * m.cos(2*y) * m.cos(z) density_sym = sym.var("density") jump_identity_sym = ( sym.div(sym.S(knl, sym.normal(3).as_vector()*density_sym, qbx_forced_limit="avg")) + sym.D(knl, density_sym, qbx_forced_limit="avg")) else: raise ValueError("unexpected value of 'relation': %s" % relation) bound_jump_identity = bind(qbx, jump_identity_sym) jump_identity = bound_jump_identity(queue, density=density) err = ( norm(qbx, queue, jump_identity, np.inf) / norm(qbx, queue, density, np.inf)) print("ERROR", qbx.h_max, err) eoc_rec.add_data_point(qbx.h_max, err) # {{{ visualization if visualize and relation == "nxcurls": nxcurlS_ext = bind(qbx, nxcurlS(+1))(queue, density=density) nxcurlS_avg = bind(qbx, nxcurlS("avg"))(queue, density=density) jtxyz = bind(qbx, sym.tangential_to_xyz(density_sym))( queue, density=density) from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, qbx.density_discr, target_order+3) bdry_normals = bind(qbx, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source-%s.vtu" % nel_factor, [ ("jt", jtxyz), ("nxcurlS_ext", nxcurlS_ext), ("nxcurlS_avg", nxcurlS_avg), ("bdry_normals", bdry_normals), ]) if visualize and relation == "sp": sp_ext = bind(qbx, sym.Sp(knl, density_sym, qbx_forced_limit=+1))( queue, density=density) sp_avg = bind(qbx, sym.Sp(knl, density_sym, qbx_forced_limit="avg"))( queue, density=density) from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, qbx.density_discr, target_order+3) bdry_normals = bind(qbx, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source-%s.vtu" % nel_factor, [ ("density", density), ("sp_ext", sp_ext), ("sp_avg", sp_avg), ("bdry_normals", bdry_normals), ]) # }}} print(eoc_rec) assert eoc_rec.order_estimate() >= qbx_order - 1.5
def test_3d_jump_relations(ctx_factory, relation, visualize=False): # logging.basicConfig(level=logging.INFO) cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) if relation == "div_s": target_order = 3 else: target_order = 4 qbx_order = target_order from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for nel_factor in [6, 10, 14]: from meshmode.mesh.generation import generate_torus mesh = generate_torus( 5, 2, order=target_order, n_major=2*nel_factor, n_minor=nel_factor) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory pre_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(3)) from pytential.qbx import QBXLayerPotentialSource qbx = QBXLayerPotentialSource( pre_discr, fine_order=4*target_order, qbx_order=qbx_order, fmm_order=qbx_order + 5, fmm_backend="fmmlib" ) places = GeometryCollection(qbx) density_discr = places.get_discretization(places.auto_source.geometry) from sumpy.kernel import LaplaceKernel knl = LaplaceKernel(3) def nxcurlS(qbx_forced_limit): return sym.n_cross(sym.curl(sym.S( knl, sym.cse(sym.tangential_to_xyz(density_sym), "jxyz"), qbx_forced_limit=qbx_forced_limit))) from meshmode.dof_array import thaw x, y, z = thaw(actx, density_discr.nodes()) m = actx.np if relation == "nxcurls": density_sym = sym.make_sym_vector("density", 2) jump_identity_sym = ( nxcurlS(+1) - (nxcurlS("avg") + 0.5*sym.tangential_to_xyz(density_sym))) # The tangential coordinate system is element-local, so we can't just # conjure up some globally smooth functions, interpret their values # in the tangential coordinate system, and be done. Instead, generate # an XYZ function and project it. density = bind(places, sym.xyz_to_tangential(sym.make_sym_vector("jxyz", 3)))( actx, jxyz=sym.make_obj_array([ m.cos(0.5*x) * m.cos(0.5*y) * m.cos(0.5*z), m.sin(0.5*x) * m.cos(0.5*y) * m.sin(0.5*z), m.sin(0.5*x) * m.cos(0.5*y) * m.cos(0.5*z), ])) elif relation == "sp": density = m.cos(2*x) * m.cos(2*y) * m.cos(z) density_sym = sym.var("density") jump_identity_sym = ( sym.Sp(knl, density_sym, qbx_forced_limit=+1) - (sym.Sp(knl, density_sym, qbx_forced_limit="avg") - 0.5*density_sym)) elif relation == "div_s": density = m.cos(2*x) * m.cos(2*y) * m.cos(z) density_sym = sym.var("density") jump_identity_sym = ( sym.div(sym.S(knl, sym.normal(3).as_vector()*density_sym, qbx_forced_limit="avg")) + sym.D(knl, density_sym, qbx_forced_limit="avg")) else: raise ValueError("unexpected value of 'relation': %s" % relation) bound_jump_identity = bind(places, jump_identity_sym) jump_identity = bound_jump_identity(actx, density=density) h_max = bind(places, sym.h_max(qbx.ambient_dim))(actx) err = ( norm(density_discr, jump_identity, np.inf) / norm(density_discr, density, np.inf)) print("ERROR", h_max, err) eoc_rec.add_data_point(h_max, err) # {{{ visualization if visualize and relation == "nxcurls": nxcurlS_ext = bind(places, nxcurlS(+1))(actx, density=density) nxcurlS_avg = bind(places, nxcurlS("avg"))(actx, density=density) jtxyz = bind(places, sym.tangential_to_xyz(density_sym))( actx, density=density) from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(actx, qbx.density_discr, target_order+3) bdry_normals = bind(places, sym.normal(3))(actx)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source-%s.vtu" % nel_factor, [ ("jt", jtxyz), ("nxcurlS_ext", nxcurlS_ext), ("nxcurlS_avg", nxcurlS_avg), ("bdry_normals", bdry_normals), ]) if visualize and relation == "sp": op = sym.Sp(knl, density_sym, qbx_forced_limit=+1) sp_ext = bind(places, op)(actx, density=density) op = sym.Sp(knl, density_sym, qbx_forced_limit="avg") sp_avg = bind(places, op)(actx, density=density) from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(actx, qbx.density_discr, target_order+3) bdry_normals = bind(places, sym.normal(3))(actx).as_vector(dtype=object) bdry_vis.write_vtk_file("source-%s.vtu" % nel_factor, [ ("density", density), ("sp_ext", sp_ext), ("sp_avg", sp_avg), ("bdry_normals", bdry_normals), ]) # }}} print(eoc_rec) assert eoc_rec.order_estimate() >= qbx_order - 1.5
eoc_rec.add_data_point(h, err) print(eoc_rec) assert (eoc_rec.order_estimate() >= order - 0.5 or eoc_rec.max_error() < 1.7e-13) # }}} # {{{ element orientation: canned 3D meshes # python test_meshmode.py "test_sanity_balls(cl._csc, "disk-radius-1.step", 2, 2, visualize=True)" # noqa @pytest.mark.parametrize(("what", "mesh_gen_func"), [ ("ball", lambda: mgen.generate_icosahedron(1, 1)), ("torus", lambda: mgen.generate_torus(5, 1)), ]) def test_orientation_3d(actx_factory, what, mesh_gen_func, visualize=False): pytest.importorskip("pytential") logging.basicConfig(level=logging.INFO) actx = actx_factory() mesh = mesh_gen_func() logger.info("%d elements", mesh.nelements) from meshmode.discretization import Discretization discr = Discretization(actx, mesh, PolynomialWarpAndBlendGroupFactory(3)) from pytential import bind, sym
mesh = perform_flips(mesh, flippy, skip_tests=True) mesh_orient = find_volume_mesh_element_orientations(mesh) assert ((mesh_orient < 0) == (flippy > 0)).all() # }}} # {{{ element orientation: canned 3D meshes # python test_meshmode.py 'test_sanity_balls(cl._csc, "disk-radius-1.step", 2, 2, visualize=True)' # noqa @pytest.mark.parametrize(("what", "mesh_gen_func"), [ ("ball", lambda: mgen.generate_icosahedron(1, 1)), ("torus", lambda: mgen.generate_torus(5, 1)), ]) def test_3d_orientation(ctx_factory, what, mesh_gen_func, visualize=False): pytest.importorskip("pytential") logging.basicConfig(level=logging.INFO) ctx = ctx_factory() queue = cl.CommandQueue(ctx) mesh = mesh_gen_func() logger.info("%d elements" % mesh.nelements) from meshmode.discretization import Discretization discr = Discretization(ctx, mesh,
def main(): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import generate_torus rout = 10 rin = 1 if 1: base_mesh = generate_torus( rout, rin, 40, 4, mesh_order) from meshmode.mesh.processing import affine_map, merge_disjoint_meshes # nx = 1 # ny = 1 nz = 1 dz = 0 meshes = [ affine_map( base_mesh, A=np.diag([1, 1, 1]), b=np.array([0, 0, iz*dz])) for iz in range(nz)] mesh = merge_disjoint_meshes(meshes, single_group=True) if 0: from meshmode.mesh.visualization import draw_curve draw_curve(mesh) import matplotlib.pyplot as plt plt.show() pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import ( QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx, _ = QBXLayerPotentialSource( pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order ).with_refinement() density_discr = qbx.density_discr # {{{ describe bvp from sumpy.kernel import LaplaceKernel kernel = LaplaceKernel(3) cse = sym.cse sigma_sym = sym.var("sigma") #sqrt_w = sym.sqrt_jac_q_weight(3) sqrt_w = 1 inv_sqrt_w_sigma = cse(sigma_sym/sqrt_w) # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = (loc_sign*0.5*sigma_sym + sqrt_w*( sym.S(kernel, inv_sqrt_w_sigma) + sym.D(kernel, inv_sqrt_w_sigma) )) # }}} bound_op = bind(qbx, bdry_op_sym) # {{{ fix rhs and solve nodes = density_discr.nodes().with_queue(queue) source = np.array([rout, 0, 0]) def u_incoming_func(x): # return 1/cl.clmath.sqrt( (x[0] - source[0])**2 # +(x[1] - source[1])**2 # +(x[2] - source[2])**2 ) return 1.0/la.norm(x.get()-source[:, None], axis=0) bc = cl.array.to_device(queue, u_incoming_func(nodes)) bvp_rhs = bind(qbx, sqrt_w*sym.var("bc"))(queue, bc=bc) from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(queue, "sigma", dtype=np.float64), bvp_rhs, tol=1e-14, progress=True, stall_iterations=0, hard_failure=True) sigma = bind(qbx, sym.var("sigma")/sqrt_w)(queue, sigma=gmres_result.solution) # }}} from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, 20) bdry_vis.write_vtk_file("laplace.vtu", [ ("sigma", sigma), ]) # {{{ postprocess/visualize repr_kwargs = dict(qbx_forced_limit=None) representation_sym = ( sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) + sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs)) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(3), extent=20, npoints=50) targets = cl.array.to_device(queue, fplot.points) qbx_stick_out = qbx.copy(target_stick_out_factor=0.2) try: fld_in_vol = bind( (qbx_stick_out, PointsTarget(targets)), representation_sym)(queue, sigma=sigma).get() except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed", e.failed_target_flags.get(queue)) ] ) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential-laplace-3d.vts", [ ("potential", fld_in_vol), ] )
def test_visualizers(actx_factory, dim, group_cls): actx = actx_factory() nelements = 64 target_order = 4 is_simplex = issubclass(group_cls, SimplexElementGroup) if dim == 1: mesh = mgen.make_curve_mesh(mgen.NArmedStarfish(5, 0.25), np.linspace(0.0, 1.0, nelements + 1), target_order) elif dim == 2: if is_simplex: mesh = mgen.generate_torus(5.0, 1.0, order=target_order) else: mesh = mgen.generate_regular_rect_mesh(a=(0, ) * dim, b=(1, ) * dim, nelements_per_axis=(4, ) * dim, group_cls=group_cls, order=target_order) elif dim == 3: if is_simplex: mesh = mgen.generate_warped_rect_mesh(dim, target_order, nelements_side=4) else: mesh = mgen.generate_regular_rect_mesh(a=(0, ) * dim, b=(1, ) * dim, nelements_per_axis=(4, ) * dim, group_cls=group_cls, order=target_order) else: raise ValueError("unknown dimensionality") if is_simplex: group_factory = InterpolatoryQuadratureSimplexGroupFactory else: group_factory = LegendreGaussLobattoTensorProductGroupFactory from meshmode.discretization import Discretization discr = Discretization(actx, mesh, group_factory(target_order)) nodes = thaw(discr.nodes(), actx) f = actx.np.sqrt(sum(nodes**2)) + 1j * nodes[0] g = VisualizerData(g=f) names_and_fields = [("f", f), ("g", g)] names_and_fields = [("f", f)] from meshmode.discretization.visualization import make_visualizer vis = make_visualizer(actx, discr, target_order) eltype = "simplex" if is_simplex else "box" basename = f"visualizer_vtk_{eltype}_{dim}d" vis.write_vtk_file(f"{basename}_linear.vtu", names_and_fields, overwrite=True) with pytest.raises(RuntimeError): vis.write_vtk_file(f"{basename}_lagrange.vtu", names_and_fields, overwrite=True, use_high_order=True) try: basename = f"visualizer_xdmf_{eltype}_{dim}d" vis.write_xdmf_file(f"{basename}.xmf", names_and_fields, overwrite=True) except ImportError: logger.info("h5py not available") if mesh.dim == 2 and is_simplex: try: vis.show_scalar_in_matplotlib_3d(f, do_show=False) except ImportError: logger.info("matplotlib not available") if mesh.dim <= 2 and is_simplex: try: vis.show_scalar_in_mayavi(f, do_show=False) except ImportError: logger.info("mayavi not available") vis = make_visualizer(actx, discr, target_order, force_equidistant=True) basename = f"visualizer_vtk_{eltype}_{dim}d" vis.write_vtk_file(f"{basename}_lagrange.vtu", names_and_fields, overwrite=True, use_high_order=True)
def main(mesh_name="torus", visualize=False): import logging logging.basicConfig(level=logging.WARNING) # INFO for more progress info cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) if mesh_name == "torus": rout = 10 rin = 1 from meshmode.mesh.generation import generate_torus base_mesh = generate_torus( rout, rin, 40, 4, mesh_order) from meshmode.mesh.processing import affine_map, merge_disjoint_meshes # nx = 1 # ny = 1 nz = 1 dz = 0 meshes = [ affine_map( base_mesh, A=np.diag([1, 1, 1]), b=np.array([0, 0, iz*dz])) for iz in range(nz)] mesh = merge_disjoint_meshes(meshes, single_group=True) if visualize: from meshmode.mesh.visualization import draw_curve draw_curve(mesh) import matplotlib.pyplot as plt plt.show() else: raise ValueError(f"unknown mesh name: {mesh_name}") pre_density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order)) from pytential.qbx import ( QBXLayerPotentialSource, QBXTargetAssociationFailedException) qbx = QBXLayerPotentialSource( pre_density_discr, fine_order=bdry_ovsmp_quad_order, qbx_order=qbx_order, fmm_order=fmm_order, ) from sumpy.visualization import FieldPlotter fplot = FieldPlotter(np.zeros(3), extent=20, npoints=50) targets = actx.from_numpy(fplot.points) from pytential import GeometryCollection places = GeometryCollection({ "qbx": qbx, "qbx_target_assoc": qbx.copy(target_association_tolerance=0.2), "targets": PointsTarget(targets) }, auto_where="qbx") density_discr = places.get_discretization("qbx") # {{{ describe bvp from sumpy.kernel import LaplaceKernel kernel = LaplaceKernel(3) sigma_sym = sym.var("sigma") #sqrt_w = sym.sqrt_jac_q_weight(3) sqrt_w = 1 inv_sqrt_w_sigma = sym.cse(sigma_sym/sqrt_w) # -1 for interior Dirichlet # +1 for exterior Dirichlet loc_sign = +1 bdry_op_sym = (loc_sign*0.5*sigma_sym + sqrt_w*( sym.S(kernel, inv_sqrt_w_sigma, qbx_forced_limit=+1) + sym.D(kernel, inv_sqrt_w_sigma, qbx_forced_limit="avg") )) # }}} bound_op = bind(places, bdry_op_sym) # {{{ fix rhs and solve from meshmode.dof_array import thaw, flatten, unflatten nodes = thaw(actx, density_discr.nodes()) source = np.array([rout, 0, 0]) def u_incoming_func(x): from pytools.obj_array import obj_array_vectorize x = obj_array_vectorize(actx.to_numpy, flatten(x)) x = np.array(list(x)) # return 1/cl.clmath.sqrt( (x[0] - source[0])**2 # +(x[1] - source[1])**2 # +(x[2] - source[2])**2 ) return 1.0/la.norm(x - source[:, None], axis=0) bc = unflatten(actx, density_discr, actx.from_numpy(u_incoming_func(nodes))) bvp_rhs = bind(places, sqrt_w*sym.var("bc"))(actx, bc=bc) from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(actx, "sigma", dtype=np.float64), bvp_rhs, tol=1e-14, progress=True, stall_iterations=0, hard_failure=True) sigma = bind(places, sym.var("sigma")/sqrt_w)( actx, sigma=gmres_result.solution) # }}} from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(actx, density_discr, 20) bdry_vis.write_vtk_file("laplace.vtu", [ ("sigma", sigma), ]) # {{{ postprocess/visualize repr_kwargs = dict( source="qbx_target_assoc", target="targets", qbx_forced_limit=None) representation_sym = ( sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) + sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs)) try: fld_in_vol = actx.to_numpy( bind(places, representation_sym)(actx, sigma=sigma)) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file("laplace-dirichlet-3d-failed-targets.vts", [ ("failed", e.failed_target_flags.get(queue)), ]) raise #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("laplace-dirichlet-3d-potential.vts", [ ("potential", fld_in_vol), ])
def test_3d_jump_relations(actx_factory, relation, visualize=False): # logging.basicConfig(level=logging.INFO) actx = actx_factory() if relation == "div_s": target_order = 3 else: target_order = 4 qbx_order = target_order if relation == "sp": resolutions = [10, 14, 18] else: resolutions = [6, 10, 14] from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for nel_factor in resolutions: from meshmode.mesh.generation import generate_torus mesh = generate_torus( 5, 2, n_major=2 * nel_factor, n_minor=nel_factor, order=target_order, ) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory pre_density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) from pytential.qbx import QBXLayerPotentialSource qbx = QBXLayerPotentialSource(pre_density_discr, fine_order=5 * target_order, qbx_order=qbx_order, fmm_order=qbx_order + 5, fmm_backend="fmmlib") places = GeometryCollection(qbx) density_discr = places.get_discretization(places.auto_source.geometry) from sumpy.kernel import LaplaceKernel knl = LaplaceKernel(places.ambient_dim) def nxcurlS(qbx_forced_limit): sigma_sym = sym.cse(sym.tangential_to_xyz(density_sym), "jxyz") return sym.n_cross( sym.curl( sym.S(knl, sigma_sym, qbx_forced_limit=qbx_forced_limit))) x, y, z = thaw(density_discr.nodes(), actx) if relation == "nxcurls": density_sym = sym.make_sym_vector("density", 2) jump_identity_sym = (nxcurlS(+1) - nxcurlS("avg") - 0.5 * sym.tangential_to_xyz(density_sym)) # The tangential coordinate system is element-local, so we can't just # conjure up some globally smooth functions, interpret their values # in the tangential coordinate system, and be done. Instead, generate # an XYZ function and project it. jxyz = sym.make_obj_array([ actx.np.cos(0.5 * x) * actx.np.cos(0.5 * y) * actx.np.cos(0.5 * z), actx.np.sin(0.5 * x) * actx.np.cos(0.5 * y) * actx.np.sin(0.5 * z), actx.np.sin(0.5 * x) * actx.np.cos(0.5 * y) * actx.np.cos(0.5 * z), ]) density = bind( places, sym.xyz_to_tangential(sym.make_sym_vector("jxyz", 3)))(actx, jxyz=jxyz) elif relation == "sp": density_sym = sym.var("density") jump_identity_sym = ( 0.5 * density_sym + sym.Sp(knl, density_sym, qbx_forced_limit=+1) - sym.Sp(knl, density_sym, qbx_forced_limit="avg")) density = actx.np.cos(2 * x) * actx.np.cos(2 * y) * actx.np.cos(z) elif relation == "div_s": density_sym = sym.var("density") sigma_sym = sym.normal( places.ambient_dim).as_vector() * density_sym jump_identity_sym = ( sym.div(sym.S(knl, sigma_sym, qbx_forced_limit="avg")) + sym.D(knl, density_sym, qbx_forced_limit="avg")) density = actx.np.cos(2 * x) * actx.np.cos(2 * y) * actx.np.cos(z) else: raise ValueError(f"unexpected value of 'relation': '{relation}'") bound_jump_identity = bind(places, jump_identity_sym) jump_identity = bound_jump_identity(actx, density=density) h_max = actx.to_numpy( bind(places, sym.h_max(places.ambient_dim))(actx)) err = actx.to_numpy( norm(density_discr, jump_identity, np.inf) / norm(density_discr, density, np.inf)) eoc_rec.add_data_point(h_max, err) logging.info("error: nel %d h_max %.5e %.5e", nel_factor, h_max, err) # {{{ visualization if not visualize: continue from meshmode.discretization.visualization import make_visualizer vis = make_visualizer(actx, density_discr, target_order) normals = bind(places, sym.normal(places.ambient_dim).as_vector())(actx) error = actx.np.log10(actx.np.abs(jump_identity) + 1.0e-15) if relation == "nxcurls": nxcurlS_ext = bind(places, nxcurlS(+1))(actx, density=density) nxcurlS_avg = bind(places, nxcurlS("avg"))(actx, density=density) jtxyz = bind(places, sym.tangential_to_xyz(density_sym))(actx, density=density) vis.write_vtk_file(f"source-nxcurls-{nel_factor:03d}.vtu", [ ("jt", jtxyz), ("nxcurlS_ext", nxcurlS_ext), ("nxcurlS_avg", nxcurlS_avg), ("bdry_normals", normals), ("error", error), ]) elif relation == "sp": op = sym.Sp(knl, density_sym, qbx_forced_limit=+1) sp_ext = bind(places, op)(actx, density=density) op = sym.Sp(knl, density_sym, qbx_forced_limit="avg") sp_avg = bind(places, op)(actx, density=density) vis.write_vtk_file(f"source-sp-{nel_factor:03d}.vtu", [ ("density", density), ("sp_ext", sp_ext), ("sp_avg", sp_avg), ("bdry_normals", normals), ("error", error), ]) elif relation == "div_s": vis.write_vtk_file(f"source-div-{nel_factor:03d}.vtu", [ ("density", density), ("bdry_normals", normals), ("error", error), ]) # }}} logger.info("\n%s", str(eoc_rec)) assert eoc_rec.order_estimate() >= qbx_order - 1.5