def _test_node_vertex_consistency_simplex(mesh, mgrp, tol): if mgrp.nelements == 0: return True resampling_mat = mp.resampling_matrix( mp.simplex_best_available_basis(mgrp.dim, mgrp.order), mgrp.vertex_unit_coordinates().T, mgrp.unit_nodes) # dim, nelments, nnvertices map_vertices = np.einsum( "ij,dej->dei", resampling_mat, mgrp.nodes) grp_vertices = mesh.vertices[:, mgrp.vertex_indices] per_element_vertex_errors = np.sqrt(np.sum( np.sum((map_vertices - grp_vertices)**2, axis=0), axis=-1)) if tol is None: tol = 1e3 * np.finfo(per_element_vertex_errors.dtype).eps from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) size = la.norm(bbox_max-bbox_min) assert np.max(per_element_vertex_errors) < tol*size, \ np.max(per_element_vertex_errors) return True
def _test_node_vertex_consistency_simplex(mesh, mgrp): if mgrp.nelements == 0: return True resampling_mat = mp.resampling_matrix( mp.simplex_best_available_basis(mgrp.dim, mgrp.order), mgrp.vertex_unit_coordinates().T, mgrp.unit_nodes) # dim, nelments, nnvertices map_vertices = np.einsum( "ij,dej->dei", resampling_mat, mgrp.nodes) grp_vertices = mesh.vertices[:, mgrp.vertex_indices] per_element_vertex_errors = np.sqrt(np.sum( np.sum((map_vertices - grp_vertices)**2, axis=0), axis=-1)) tol = 1e3 * np.finfo(per_element_vertex_errors.dtype).eps from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) size = la.norm(bbox_max-bbox_min) assert np.max(per_element_vertex_errors) < tol*size, \ np.max(per_element_vertex_errors) return True
def make_element_lookup_tree(mesh, eps=1e-12): from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_min -= eps bbox_max += eps tree = SpatialBinaryTreeBucket(bbox_min, bbox_max) for igrp, grp in enumerate(mesh.groups): for iel_grp in range(grp.nelements): el_vertices = mesh.vertices[:, grp.vertex_indices[iel_grp]] el_bbox_min = np.min(el_vertices, axis=-1) - eps el_bbox_max = np.max(el_vertices, axis=-1) + eps tree.insert((igrp, iel_grp), (el_bbox_min, el_bbox_max)) return tree
def make_element_lookup_tree(mesh, eps=1e-12): from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_min -= eps bbox_max += eps tree = SpatialBinaryTreeBucket(bbox_min, bbox_max) for igrp, grp in enumerate(mesh.groups): for iel_grp in range(grp.nelements): el_vertices = mesh.vertices[:, grp.vertex_indices[iel_grp]] el_bbox_min = np.min(el_vertices, axis=-1) - eps el_bbox_max = np.max(el_vertices, axis=-1) + eps tree.insert((igrp, iel_grp), (el_bbox_min, el_bbox_max)) return tree
def replicate_along_axes(mesh, shape, sep_ratio): from meshmode.mesh.processing import (find_bounding_box, affine_map, merge_disjoint_meshes) bbox = find_bounding_box(mesh) sizes = bbox[1] - bbox[0] meshes = [mesh] for i in range(mesh.ambient_dim): for j in range(1, shape[i]): vec = np.zeros(mesh.ambient_dim) vec[i] = j * sizes[i] * (1 + sep_ratio) meshes.append(affine_map(mesh, A=None, b=vec)) # FIXME: https://gitlab.tiker.net/inducer/pytential/issues/6 mesh = merge_disjoint_meshes(meshes, single_group=True) meshes = [mesh] return mesh
def test_lookup_tree(do_plot=False): from meshmode.mesh.generation import make_curve_mesh, cloverleaf mesh = make_curve_mesh(cloverleaf, np.linspace(0, 1, 1000), order=3) from meshmode.mesh.tools import make_element_lookup_tree tree = make_element_lookup_tree(mesh) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) extent = bbox_max - bbox_min for i in range(20): pt = bbox_min + np.random.rand(2) * extent print(pt) for igrp, iel in tree.generate_matches(pt): print(igrp, iel) if do_plot: with open("tree.dat", "w") as outf: tree.visualize(outf)
def test_lookup_tree(do_plot=False): from meshmode.mesh.generation import make_curve_mesh, cloverleaf mesh = make_curve_mesh(cloverleaf, np.linspace(0, 1, 1000), order=3) from meshmode.mesh.tools import make_element_lookup_tree tree = make_element_lookup_tree(mesh) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) extent = bbox_max-bbox_min for i in range(20): pt = bbox_min + np.random.rand(2) * extent print(pt) for igrp, iel in tree.generate_matches(pt): print(igrp, iel) if do_plot: with open("tree.dat", "w") as outf: tree.visualize(outf)
def _test_node_vertex_consistency_resampling(mesh, mgrp, tol): if mesh.vertices is None: return True if mgrp.nelements == 0: return True if isinstance(mgrp, _ModepyElementGroup): basis = mp.basis_for_space(mgrp._modepy_space, mgrp._modepy_shape).functions else: raise TypeError(f"unsupported group type: {type(mgrp).__name__}") resampling_mat = mp.resampling_matrix( basis, mgrp.vertex_unit_coordinates().T, mgrp.unit_nodes) # dim, nelments, nnvertices map_vertices = np.einsum( "ij,dej->dei", resampling_mat, mgrp.nodes) grp_vertices = mesh.vertices[:, mgrp.vertex_indices] per_element_vertex_errors = np.sqrt(np.sum( np.sum((map_vertices - grp_vertices)**2, axis=0), axis=-1)) if tol is None: tol = 1e3 * np.finfo(per_element_vertex_errors.dtype).eps from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) size = la.norm(bbox_max-bbox_min) max_el_vertex_error = np.max(per_element_vertex_errors) assert max_el_vertex_error < tol*size, max_el_vertex_error return True
def test_pec_mfie_extinction(ctx_getter, case, visualize=False): """For (say) is_interior=False (the 'exterior' MFIE), this test verifies extinction of the combined (incoming + scattered) field on the interior of the scatterer. """ logging.basicConfig(level=logging.INFO) cl_ctx = ctx_getter() queue = cl.CommandQueue(cl_ctx) np.random.seed(12) knl_kwargs = {"k": case.k} # {{{ come up with a solution to Maxwell's equations j_sym = sym.make_sym_vector("j", 3) jt_sym = sym.make_sym_vector("jt", 2) rho_sym = sym.var("rho") from pytential.symbolic.pde.maxwell import ( PECChargeCurrentMFIEOperator, get_sym_maxwell_point_source, get_sym_maxwell_plane_wave) mfie = PECChargeCurrentMFIEOperator() test_source = case.get_source(queue) calc_patch = CalculusPatch(np.array([-3, 0, 0]), h=0.01) calc_patch_tgt = PointsTarget(cl.array.to_device(queue, calc_patch.points)) rng = cl.clrandom.PhiloxGenerator(cl_ctx, seed=12) src_j = rng.normal(queue, (3, test_source.nnodes), dtype=np.float64) def eval_inc_field_at(tgt): if 0: # plane wave return bind( tgt, get_sym_maxwell_plane_wave( amplitude_vec=np.array([1, 1, 1]), v=np.array([1, 0, 0]), omega=case.k) )(queue) else: # point source return bind( (test_source, tgt), get_sym_maxwell_point_source(mfie.kernel, j_sym, mfie.k) )(queue, j=src_j, k=case.k) pde_test_inc = EHField( vector_from_device(queue, eval_inc_field_at(calc_patch_tgt))) source_maxwell_resids = [ calc_patch.norm(x, np.inf) / calc_patch.norm(pde_test_inc.e, np.inf) for x in frequency_domain_maxwell( calc_patch, pde_test_inc.e, pde_test_inc.h, case.k)] print("Source Maxwell residuals:", source_maxwell_resids) assert max(source_maxwell_resids) < 1e-6 # }}} loc_sign = -1 if case.is_interior else +1 from pytools.convergence import EOCRecorder eoc_rec_repr_maxwell = EOCRecorder() eoc_pec_bc = EOCRecorder() eoc_rec_e = EOCRecorder() eoc_rec_h = EOCRecorder() from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder for resolution in case.resolutions: scat_mesh = case.get_mesh(resolution, case.target_order) observation_mesh = case.get_observation_mesh(case.target_order) pre_scat_discr = Discretization( cl_ctx, scat_mesh, InterpolatoryQuadratureSimplexGroupFactory(case.target_order)) qbx, _ = QBXLayerPotentialSource( pre_scat_discr, fine_order=4*case.target_order, qbx_order=case.qbx_order, fmm_level_to_order=SimpleExpansionOrderFinder( case.fmm_tolerance), fmm_backend=case.fmm_backend ).with_refinement(_expansion_disturbance_tolerance=0.05) h_max = qbx.h_max scat_discr = qbx.density_discr obs_discr = Discretization( cl_ctx, observation_mesh, InterpolatoryQuadratureSimplexGroupFactory(case.target_order)) inc_field_scat = EHField(eval_inc_field_at(scat_discr)) inc_field_obs = EHField(eval_inc_field_at(obs_discr)) # {{{ system solve inc_xyz_sym = EHField(sym.make_sym_vector("inc_fld", 6)) bound_j_op = bind(qbx, mfie.j_operator(loc_sign, jt_sym)) j_rhs = bind(qbx, mfie.j_rhs(inc_xyz_sym.h))( queue, inc_fld=inc_field_scat.field, **knl_kwargs) gmres_settings = dict( tol=case.gmres_tol, progress=True, hard_failure=True, stall_iterations=50, no_progress_factor=1.05) from pytential.solve import gmres gmres_result = gmres( bound_j_op.scipy_op(queue, "jt", np.complex128, **knl_kwargs), j_rhs, **gmres_settings) jt = gmres_result.solution bound_rho_op = bind(qbx, mfie.rho_operator(loc_sign, rho_sym)) rho_rhs = bind(qbx, mfie.rho_rhs(jt_sym, inc_xyz_sym.e))( queue, jt=jt, inc_fld=inc_field_scat.field, **knl_kwargs) gmres_result = gmres( bound_rho_op.scipy_op(queue, "rho", np.complex128, **knl_kwargs), rho_rhs, **gmres_settings) rho = gmres_result.solution # }}} jxyz = bind(qbx, sym.tangential_to_xyz(jt_sym))(queue, jt=jt) # {{{ volume eval sym_repr = mfie.scattered_volume_field(jt_sym, rho_sym) def eval_repr_at(tgt, source=None): if source is None: source = qbx return bind((source, tgt), sym_repr)(queue, jt=jt, rho=rho, **knl_kwargs) pde_test_repr = EHField( vector_from_device(queue, eval_repr_at(calc_patch_tgt))) maxwell_residuals = [ calc_patch.norm(x, np.inf) / calc_patch.norm(pde_test_repr.e, np.inf) for x in frequency_domain_maxwell( calc_patch, pde_test_repr.e, pde_test_repr.h, case.k)] print("Maxwell residuals:", maxwell_residuals) eoc_rec_repr_maxwell.add_data_point(h_max, max(maxwell_residuals)) # }}} # {{{ check PEC BC on total field bc_repr = EHField(mfie.scattered_volume_field( jt_sym, rho_sym, qbx_forced_limit=loc_sign)) pec_bc_e = sym.n_cross(bc_repr.e + inc_xyz_sym.e) pec_bc_h = sym.normal(3).as_vector().dot(bc_repr.h + inc_xyz_sym.h) eh_bc_values = bind(qbx, sym.join_fields(pec_bc_e, pec_bc_h))( queue, jt=jt, rho=rho, inc_fld=inc_field_scat.field, **knl_kwargs) def scat_norm(f): return norm(qbx, queue, f, p=np.inf) e_bc_residual = scat_norm(eh_bc_values[:3]) / scat_norm(inc_field_scat.e) h_bc_residual = scat_norm(eh_bc_values[3]) / scat_norm(inc_field_scat.h) print("E/H PEC BC residuals:", h_max, e_bc_residual, h_bc_residual) eoc_pec_bc.add_data_point(h_max, max(e_bc_residual, h_bc_residual)) # }}} # {{{ visualization if visualize: from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, scat_discr, case.target_order+3) bdry_normals = bind(scat_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source-%s.vtu" % resolution, [ ("j", jxyz), ("rho", rho), ("Einc", inc_field_scat.e), ("Hinc", inc_field_scat.h), ("bdry_normals", bdry_normals), ("e_bc_residual", eh_bc_values[:3]), ("h_bc_residual", eh_bc_values[3]), ]) fplot = make_field_plotter_from_bbox( find_bounding_box(scat_discr.mesh), h=(0.05, 0.05, 0.3), extend_factor=0.3) from pytential.qbx import QBXTargetAssociationFailedException qbx_tgt_tol = qbx.copy(target_association_tolerance=0.2) fplot_tgt = PointsTarget(cl.array.to_device(queue, fplot.points)) try: fplot_repr = eval_repr_at(fplot_tgt, source=qbx_tgt_tol) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed_targets", e.failed_target_flags.get(queue)) ]) raise fplot_repr = EHField(vector_from_device(queue, fplot_repr)) fplot_inc = EHField( vector_from_device(queue, eval_inc_field_at(fplot_tgt))) fplot.write_vtk_file( "potential-%s.vts" % resolution, [ ("E", fplot_repr.e), ("H", fplot_repr.h), ("Einc", fplot_inc.e), ("Hinc", fplot_inc.h), ] ) # }}} # {{{ error in E, H obs_repr = EHField(eval_repr_at(obs_discr)) def obs_norm(f): return norm(obs_discr, queue, f, p=np.inf) rel_err_e = (obs_norm(inc_field_obs.e + obs_repr.e) / obs_norm(inc_field_obs.e)) rel_err_h = (obs_norm(inc_field_obs.h + obs_repr.h) / obs_norm(inc_field_obs.h)) # }}} print("ERR", h_max, rel_err_h, rel_err_e) eoc_rec_h.add_data_point(h_max, rel_err_h) eoc_rec_e.add_data_point(h_max, rel_err_e) print("--------------------------------------------------------") print("is_interior=%s" % case.is_interior) print("--------------------------------------------------------") good = True for which_eoc, eoc_rec, order_tol in [ ("maxwell", eoc_rec_repr_maxwell, 1.5), ("PEC BC", eoc_pec_bc, 1.5), ("H", eoc_rec_h, 1.5), ("E", eoc_rec_e, 1.5)]: print(which_eoc) print(eoc_rec.pretty_print()) if len(eoc_rec.history) > 1: if eoc_rec.order_estimate() < case.qbx_order - order_tol: good = False assert good
def main(): # cl.array.to_device(queue, numpy_array) from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource("ellipsoid.step"), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h]) from meshmode.mesh.processing import perform_flips # Flip elements--gmsh generates inside-out geometry. mesh = perform_flips(mesh, np.ones(mesh.nelements)) print("%d elements" % mesh.nelements) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5*(bbox_min+bbox_max) bbox_size = max(bbox_max-bbox_min) / 2 logger.info("%d elements" % mesh.nelements) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) qbx = QBXLayerPotentialSource(density_discr, 4*target_order, qbx_order, fmm_order=qbx_order + 10, fmm_backend="fmmlib") from pytential.symbolic.pde.maxwell import MuellerAugmentedMFIEOperator pde_op = MuellerAugmentedMFIEOperator( omega=0.4, epss=[1.4, 1.0], mus=[1.2, 1.0], ) from pytential import bind, sym unk = pde_op.make_unknown("sigma") sym_operator = pde_op.operator(unk) sym_rhs = pde_op.rhs( sym.make_sym_vector("Einc", 3), sym.make_sym_vector("Hinc", 3)) sym_repr = pde_op.representation(0, unk) if 1: expr = sym_repr print(sym.pretty(expr)) print("#"*80) from pytential.target import PointsTarget tgt_points=np.zeros((3,1)) tgt_points[0,0] = 100 tgt_points[1,0] = -200 tgt_points[2,0] = 300 bound_op = bind((qbx, PointsTarget(tgt_points)), expr) print(bound_op.code) if 1: def green3e(x,y,z,source,strength,k): # electric field corresponding to dyadic green's function # due to monochromatic electric dipole located at "source". # "strength" is the the intensity of the dipole. # E = (I + Hess)(exp(ikr)/r) dot (strength) # dx = x - source[0] dy = y - source[1] dz = z - source[2] rr = np.sqrt(dx**2 + dy**2 + dz**2) fout = np.exp(1j*k*rr)/rr evec = fout*strength qmat = np.zeros((3,3),dtype=np.complex128) qmat[0,0]=(2*dx**2-dy**2-dz**2)*(1-1j*k*rr) qmat[1,1]=(2*dy**2-dz**2-dx**2)*(1-1j*k*rr) qmat[2,2]=(2*dz**2-dx**2-dy**2)*(1-1j*k*rr) qmat[0,0]=qmat[0,0]+(-k**2*dx**2*rr**2) qmat[1,1]=qmat[1,1]+(-k**2*dy**2*rr**2) qmat[2,2]=qmat[2,2]+(-k**2*dz**2*rr**2) qmat[0,1]=(3-k**2*rr**2-3*1j*k*rr)*(dx*dy) qmat[1,2]=(3-k**2*rr**2-3*1j*k*rr)*(dy*dz) qmat[2,0]=(3-k**2*rr**2-3*1j*k*rr)*(dz*dx) qmat[1,0]=qmat[0,1] qmat[2,1]=qmat[1,2] qmat[0,2]=qmat[2,0] fout=np.exp(1j*k*rr)/rr**5/k**2 fvec = fout*np.dot(qmat,strength) evec = evec + fvec return evec def green3m(x,y,z,source,strength,k): # magnetic field corresponding to dyadic green's function # due to monochromatic electric dipole located at "source". # "strength" is the the intensity of the dipole. # H = curl((I + Hess)(exp(ikr)/r) dot (strength)) = # strength \cross \grad (exp(ikr)/r) # dx = x - source[0] dy = y - source[1] dz = z - source[2] rr = np.sqrt(dx**2 + dy**2 + dz**2) fout=(1-1j*k*rr)*np.exp(1j*k*rr)/rr**3 fvec = np.zeros(3,dtype=np.complex128) fvec[0] = fout*dx fvec[1] = fout*dy fvec[2] = fout*dz hvec = np.cross(strength,fvec) return hvec def dipole3e(x,y,z,source,strength,k): # # evalaute electric and magnetic field due # to monochromatic electric dipole located at "source" # with intensity "strength" evec = green3e(x,y,z,source,strength,k) evec = evec*1j*k hvec = green3m(x,y,z,source,strength,k) return evec,hvec def dipole3m(x,y,z,source,strength,k): # # evalaute electric and magnetic field due # to monochromatic magnetic dipole located at "source" # with intensity "strength" evec = green3m(x,y,z,source,strength,k) hvec = green3e(x,y,z,source,strength,k) hvec = -hvec*1j*k return evec,hvec def dipole3eall(x,y,z,sources,strengths,k): ns = len(strengths) evec = np.zeros(3,dtype=np.complex128) hvec = np.zeros(3,dtype=np.complex128) for i in range(ns): evect,hvect = dipole3e(x,y,z,sources[i],strengths[i],k) evec = evec + evect hvec = hvec + hvect nodes = density_discr.nodes().with_queue(queue).get() source = [0.01,-0.03,0.02] # source = cl.array.to_device(queue,np.zeros(3)) # source[0] = 0.01 # source[1] =-0.03 # source[2] = 0.02 strength = np.ones(3) # evec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128)) # hvec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128)) evec = np.zeros((3,len(nodes[0])),dtype=np.complex128) hvec = np.zeros((3,len(nodes[0])),dtype=np.complex128) for i in range(len(nodes[0])): evec[:,i],hvec[:,i] = dipole3e(nodes[0][i],nodes[1][i],nodes[2][i],source,strength,k) print(np.shape(hvec)) print(type(evec)) print(type(hvec)) evec = cl.array.to_device(queue,evec) hvec = cl.array.to_device(queue,hvec) bvp_rhs = bind(qbx, sym_rhs)(queue,Einc=evec,Hinc=hvec) print(np.shape(bvp_rhs)) print(type(bvp_rhs)) # print(bvp_rhs) 1/-1 bound_op = bind(qbx, sym_operator) from pytential.solve import gmres if 0: gmres_result = gmres( bound_op.scipy_op(queue, "sigma", dtype=np.complex128, k=k), bvp_rhs, tol=1e-8, progress=True, stall_iterations=0, hard_failure=True) sigma = gmres_result.solution fld_at_tgt = bind((qbx, PointsTarget(tgt_points)), sym_repr)(queue, sigma=bvp_rhs,k=k) fld_at_tgt = np.array([ fi.get() for fi in fld_at_tgt ]) print(fld_at_tgt) 1/0 # }}} #mlab.figure(bgcolor=(1, 1, 1)) if 1: from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, target_order) bdry_normals = bind(density_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source.vtu", [ ("sigma", sigma), ("bdry_normals", bdry_normals), ]) fplot = FieldPlotter(bbox_center, extent=2*bbox_size, npoints=(150, 150, 1)) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.1) from pytential.target import PointsTarget from pytential.qbx import QBXTargetAssociationFailedException rho_sym = sym.var("rho") try: fld_in_vol = bind( (qbx_tgt_tol, PointsTarget(fplot.points)), sym.make_obj_array([ sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None), sym.d_dx(3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), sym.d_dy(3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), sym.d_dz(3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), ]) )(queue, jt=jt, rho=rho, k=k) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed_targets", e.failed_target_flags.get(queue)) ]) raise fld_in_vol = sym.make_obj_array( [fiv.get() for fiv in fld_in_vol]) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential.vts", [ ("potential", fld_in_vol[0]), ("grad", fld_in_vol[1:]), ] )
def draw_2d_mesh(mesh, draw_vertex_numbers=True, draw_element_numbers=True, draw_nodal_adjacency=False, draw_face_numbers=False, set_bounding_box=False, **kwargs): assert mesh.ambient_dim == 2 import matplotlib.pyplot as pt import matplotlib.patches as mpatches from matplotlib.path import Path for igrp, grp in enumerate(mesh.groups): for iel, el in enumerate(grp.vertex_indices): elverts = mesh.vertices[:, el] from meshmode.mesh import TensorProductElementGroup if isinstance(grp, TensorProductElementGroup) and grp.dim == 2: elverts = elverts[:, np.array([0, 1, 3, 2])] pathdata = [ (Path.MOVETO, (elverts[0, 0], elverts[1, 0])), ] for i in range(1, elverts.shape[1]): pathdata.append((Path.LINETO, (elverts[0, i], elverts[1, i]))) pathdata.append((Path.CLOSEPOLY, (elverts[0, 0], elverts[1, 0]))) codes, verts = zip(*pathdata) path = Path(verts, codes) patch = mpatches.PathPatch(path, **kwargs) pt.gca().add_patch(patch) if draw_element_numbers: centroid = (np.sum(elverts, axis=1) / elverts.shape[1]) if len(mesh.groups) == 1: el_label = str(iel) else: el_label = "%d:%d" % (igrp, iel) pt.text(centroid[0], centroid[1], el_label, fontsize=17, ha="center", va="center", bbox=dict(facecolor="white", alpha=0.5, lw=0)) if draw_vertex_numbers: for ivert, vert in enumerate(mesh.vertices.T): pt.text(vert[0], vert[1], str(ivert), fontsize=15, ha="center", va="center", color="blue", bbox=dict(facecolor="white", alpha=0.5, lw=0)) if draw_nodal_adjacency: def global_iel_to_group_and_iel(global_iel): for igrp, grp in enumerate(mesh.groups): if global_iel < grp.nelements: return grp, global_iel global_iel -= grp.nelements raise ValueError("invalid element nr") cnx = mesh.nodal_adjacency nb_starts = cnx.neighbors_starts for iel_g in range(mesh.nelements): for nb_iel_g in cnx.neighbors[nb_starts[iel_g]:nb_starts[iel_g + 1]]: assert iel_g != nb_iel_g grp, iel = global_iel_to_group_and_iel(iel_g) nb_grp, nb_iel = global_iel_to_group_and_iel(nb_iel_g) elverts = mesh.vertices[:, grp.vertex_indices[iel]] nb_elverts = mesh.vertices[:, nb_grp.vertex_indices[nb_iel]] centroid = (np.sum(elverts, axis=1) / elverts.shape[1]) nb_centroid = (np.sum(nb_elverts, axis=1) / nb_elverts.shape[1]) dx = nb_centroid - centroid start = centroid + 0.15 * dx mag = np.max(np.abs(dx)) start += 0.05 * (np.random.rand(2) - 0.5) * mag dx += 0.05 * (np.random.rand(2) - 0.5) * mag pt.arrow(start[0], start[1], 0.7 * dx[0], 0.7 * dx[1], length_includes_head=True, color="green", head_width=1e-2, lw=1e-2) if draw_face_numbers: for igrp, grp in enumerate(mesh.groups): for iel, el in enumerate(grp.vertex_indices): elverts = mesh.vertices[:, el] el_center = np.mean(elverts, axis=-1) for iface, fvi in enumerate(grp.face_vertex_indices()): face_center = (0.3 * el_center + 0.7 * np.mean(elverts[:, fvi], axis=-1)) pt.text(face_center[0], face_center[1], str(iface), fontsize=12, ha="center", va="center", color="purple", bbox=dict(facecolor="white", alpha=0.5, lw=0)) if set_bounding_box: from meshmode.mesh.processing import find_bounding_box lower, upper = find_bounding_box(mesh) pt.xlim([lower[0], upper[0]]) pt.ylim([lower[1], upper[1]])
"point_source": point_source, "point_target": point_target } # plotting grid points ambient_dim = qbx.ambient_dim if visualize: vis_grid_spacing = getattr(case, "vis_grid_spacing", (0.1, 0.1, 0.1)[:ambient_dim] ) vis_extend_factor = getattr(case, "vis_extend_factor", 0.2) from sumpy.visualization import make_field_plotter_from_bbox from meshmode.mesh.processing import find_bounding_box fplot = make_field_plotter_from_bbox( find_bounding_box(qbx.density_discr.mesh), h=vis_grid_spacing, extend_factor=vis_extend_factor) from pytential.target import PointsTarget plot_targets = PointsTarget(fplot.points) places.update({ "qbx_target_tol": qbx.copy(target_association_tolerance=0.15), "plot_targets": plot_targets }) places = GeometryCollection(places, auto_where=case.name) if case.use_refinement: from pytential.qbx.refinement import refine_geometry_collection places = refine_geometry_collection(places, **refiner_extra_kwargs)
def main(): import logging logger = logging.getLogger(__name__) logging.basicConfig(level=logging.WARNING) # INFO for more progress info from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource(cad_file_name), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h]) from meshmode.mesh.processing import perform_flips # Flip elements--gmsh generates inside-out geometry. mesh = perform_flips(mesh, np.ones(mesh.nelements)) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5*(bbox_min+bbox_max) bbox_size = max(bbox_max-bbox_min) / 2 logger.info("%d elements" % mesh.nelements) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) qbx, _ = QBXLayerPotentialSource(density_discr, 4*target_order, qbx_order, fmm_order=qbx_order + 3, target_association_tolerance=0.15).with_refinement() nodes = density_discr.nodes().with_queue(queue) angle = cl.clmath.atan2(nodes[1], nodes[0]) from pytential import bind, sym #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None)) op = sym.D(kernel, sym.var("sigma"), qbx_forced_limit=None) #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None) sigma = cl.clmath.cos(mode_nr*angle) if 0: sigma = 0*angle from random import randrange for i in range(5): sigma[randrange(len(sigma))] = 1 if isinstance(kernel, HelmholtzKernel): sigma = sigma.astype(np.complex128) fplot = FieldPlotter(bbox_center, extent=3.5*bbox_size, npoints=150) from pytential.target import PointsTarget fld_in_vol = bind( (qbx, PointsTarget(fplot.points)), op)(queue, sigma=sigma, k=k).get() #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file( "potential-3d.vts", [ ("potential", fld_in_vol) ] ) bdry_normals = bind( density_discr, sym.normal(density_discr.ambient_dim))(queue).as_vector(dtype=object) from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, target_order) bdry_vis.write_vtk_file("source-3d.vtu", [ ("sigma", sigma), ("bdry_normals", bdry_normals), ])
("u", u), ("bc", bc), #("bdry_normals", bdry_normals), ]) from sumpy.visualization import make_field_plotter_from_bbox # noqa from meshmode.mesh.processing import find_bounding_box vis_grid_spacing = (0.1, 0.1, 0.1)[:qbx.ambient_dim] if hasattr(case, "vis_grid_spacing"): vis_grid_spacing = case.vis_grid_spacing vis_extend_factor = 0.2 if hasattr(case, "vis_extend_factor"): vis_grid_spacing = case.vis_grid_spacing fplot = make_field_plotter_from_bbox(find_bounding_box(mesh), h=vis_grid_spacing, extend_factor=vis_extend_factor) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.15) from pytential.target import PointsTarget try: solved_pot = bind((qbx_tgt_tol, PointsTarget(fplot.points)), op.representation(sym.var("u")))(queue, u=weighted_u, k=case.k) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [("failed_targets", e.failed_target_flags.get(queue))])
places = { case.name: qbx, "point_source": point_source, "point_target": point_target } # plotting grid points ambient_dim = qbx.ambient_dim if visualize: vis_grid_spacing = getattr(case, "vis_grid_spacing", (0.1, 0.1, 0.1)[:ambient_dim]) vis_extend_factor = getattr(case, "vis_extend_factor", 0.2) from sumpy.visualization import make_field_plotter_from_bbox from meshmode.mesh.processing import find_bounding_box fplot = make_field_plotter_from_bbox(find_bounding_box( qbx.density_discr.mesh), h=vis_grid_spacing, extend_factor=vis_extend_factor) from pytential.target import PointsTarget plot_targets = PointsTarget(fplot.points) places.update({ "qbx_target_tol": qbx.copy(target_association_tolerance=0.15), "plot_targets": plot_targets }) places = GeometryCollection(places, auto_where=case.name) if case.use_refinement:
def main(): # cl.array.to_device(queue, numpy_array) from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource("ellipsoid.step"), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h]) from meshmode.mesh.processing import perform_flips # Flip elements--gmsh generates inside-out geometry. mesh = perform_flips(mesh, np.ones(mesh.nelements)) print("%d elements" % mesh.nelements) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5 * (bbox_min + bbox_max) bbox_size = max(bbox_max - bbox_min) / 2 logger.info("%d elements" % mesh.nelements) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) qbx = QBXLayerPotentialSource(density_discr, 4 * target_order, qbx_order, fmm_order=qbx_order + 10, fmm_backend="fmmlib") from pytential.symbolic.pde.maxwell import MuellerAugmentedMFIEOperator pde_op = MuellerAugmentedMFIEOperator( omega=0.4, epss=[1.4, 1.0], mus=[1.2, 1.0], ) from pytential import bind, sym unk = pde_op.make_unknown("sigma") sym_operator = pde_op.operator(unk) sym_rhs = pde_op.rhs(sym.make_sym_vector("Einc", 3), sym.make_sym_vector("Hinc", 3)) sym_repr = pde_op.representation(0, unk) if 1: expr = sym_repr print(sym.pretty(expr)) print("#" * 80) from pytential.target import PointsTarget tgt_points = np.zeros((3, 1)) tgt_points[0, 0] = 100 tgt_points[1, 0] = -200 tgt_points[2, 0] = 300 bound_op = bind((qbx, PointsTarget(tgt_points)), expr) print(bound_op.code) if 1: def green3e(x, y, z, source, strength, k): # electric field corresponding to dyadic green's function # due to monochromatic electric dipole located at "source". # "strength" is the the intensity of the dipole. # E = (I + Hess)(exp(ikr)/r) dot (strength) # dx = x - source[0] dy = y - source[1] dz = z - source[2] rr = np.sqrt(dx**2 + dy**2 + dz**2) fout = np.exp(1j * k * rr) / rr evec = fout * strength qmat = np.zeros((3, 3), dtype=np.complex128) qmat[0, 0] = (2 * dx**2 - dy**2 - dz**2) * (1 - 1j * k * rr) qmat[1, 1] = (2 * dy**2 - dz**2 - dx**2) * (1 - 1j * k * rr) qmat[2, 2] = (2 * dz**2 - dx**2 - dy**2) * (1 - 1j * k * rr) qmat[0, 0] = qmat[0, 0] + (-k**2 * dx**2 * rr**2) qmat[1, 1] = qmat[1, 1] + (-k**2 * dy**2 * rr**2) qmat[2, 2] = qmat[2, 2] + (-k**2 * dz**2 * rr**2) qmat[0, 1] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dx * dy) qmat[1, 2] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dy * dz) qmat[2, 0] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dz * dx) qmat[1, 0] = qmat[0, 1] qmat[2, 1] = qmat[1, 2] qmat[0, 2] = qmat[2, 0] fout = np.exp(1j * k * rr) / rr**5 / k**2 fvec = fout * np.dot(qmat, strength) evec = evec + fvec return evec def green3m(x, y, z, source, strength, k): # magnetic field corresponding to dyadic green's function # due to monochromatic electric dipole located at "source". # "strength" is the the intensity of the dipole. # H = curl((I + Hess)(exp(ikr)/r) dot (strength)) = # strength \cross \grad (exp(ikr)/r) # dx = x - source[0] dy = y - source[1] dz = z - source[2] rr = np.sqrt(dx**2 + dy**2 + dz**2) fout = (1 - 1j * k * rr) * np.exp(1j * k * rr) / rr**3 fvec = np.zeros(3, dtype=np.complex128) fvec[0] = fout * dx fvec[1] = fout * dy fvec[2] = fout * dz hvec = np.cross(strength, fvec) return hvec def dipole3e(x, y, z, source, strength, k): # # evalaute electric and magnetic field due # to monochromatic electric dipole located at "source" # with intensity "strength" evec = green3e(x, y, z, source, strength, k) evec = evec * 1j * k hvec = green3m(x, y, z, source, strength, k) return evec, hvec def dipole3m(x, y, z, source, strength, k): # # evalaute electric and magnetic field due # to monochromatic magnetic dipole located at "source" # with intensity "strength" evec = green3m(x, y, z, source, strength, k) hvec = green3e(x, y, z, source, strength, k) hvec = -hvec * 1j * k return evec, hvec def dipole3eall(x, y, z, sources, strengths, k): ns = len(strengths) evec = np.zeros(3, dtype=np.complex128) hvec = np.zeros(3, dtype=np.complex128) for i in range(ns): evect, hvect = dipole3e(x, y, z, sources[i], strengths[i], k) evec = evec + evect hvec = hvec + hvect nodes = density_discr.nodes().with_queue(queue).get() source = [0.01, -0.03, 0.02] # source = cl.array.to_device(queue,np.zeros(3)) # source[0] = 0.01 # source[1] =-0.03 # source[2] = 0.02 strength = np.ones(3) # evec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128)) # hvec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128)) evec = np.zeros((3, len(nodes[0])), dtype=np.complex128) hvec = np.zeros((3, len(nodes[0])), dtype=np.complex128) for i in range(len(nodes[0])): evec[:, i], hvec[:, i] = dipole3e(nodes[0][i], nodes[1][i], nodes[2][i], source, strength, k) print(np.shape(hvec)) print(type(evec)) print(type(hvec)) evec = cl.array.to_device(queue, evec) hvec = cl.array.to_device(queue, hvec) bvp_rhs = bind(qbx, sym_rhs)(queue, Einc=evec, Hinc=hvec) print(np.shape(bvp_rhs)) print(type(bvp_rhs)) # print(bvp_rhs) 1 / -1 bound_op = bind(qbx, sym_operator) from pytential.solve import gmres if 0: gmres_result = gmres(bound_op.scipy_op(queue, "sigma", dtype=np.complex128, k=k), bvp_rhs, tol=1e-8, progress=True, stall_iterations=0, hard_failure=True) sigma = gmres_result.solution fld_at_tgt = bind((qbx, PointsTarget(tgt_points)), sym_repr)(queue, sigma=bvp_rhs, k=k) fld_at_tgt = np.array([fi.get() for fi in fld_at_tgt]) print(fld_at_tgt) 1 / 0 # }}} #mlab.figure(bgcolor=(1, 1, 1)) if 1: from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(queue, density_discr, target_order) bdry_normals = bind(density_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source.vtu", [ ("sigma", sigma), ("bdry_normals", bdry_normals), ]) fplot = FieldPlotter(bbox_center, extent=2 * bbox_size, npoints=(150, 150, 1)) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.1) from pytential.target import PointsTarget from pytential.qbx import QBXTargetAssociationFailedException rho_sym = sym.var("rho") try: fld_in_vol = bind((qbx_tgt_tol, PointsTarget(fplot.points)), sym.make_obj_array([ sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None), sym.d_dx( 3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), sym.d_dy( 3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), sym.d_dz( 3, sym.S(pde_op.kernel, rho_sym, k=sym.var("k"), qbx_forced_limit=None)), ]))(queue, jt=jt, rho=rho, k=k) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [("failed_targets", e.failed_target_flags.get(queue))]) raise fld_in_vol = sym.make_obj_array([fiv.get() for fiv in fld_in_vol]) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("potential.vts", [ ("potential", fld_in_vol[0]), ("grad", fld_in_vol[1:]), ])
def draw_2d_mesh(mesh, draw_vertex_numbers=True, draw_element_numbers=True, draw_connectivity=False, set_bounding_box=False, **kwargs): assert mesh.ambient_dim == 2 import matplotlib.pyplot as pt import matplotlib.patches as mpatches from matplotlib.path import Path for igrp, grp in enumerate(mesh.groups): for iel, el in enumerate(grp.vertex_indices): elverts = mesh.vertices[:, el] pathdata = [ (Path.MOVETO, (elverts[0, 0], elverts[1, 0])), ] for i in range(1, elverts.shape[1]): pathdata.append( (Path.LINETO, (elverts[0, i], elverts[1, i])) ) pathdata.append( (Path.CLOSEPOLY, (elverts[0, 0], elverts[1, 0]))) codes, verts = zip(*pathdata) path = Path(verts, codes) patch = mpatches.PathPatch(path, **kwargs) pt.gca().add_patch(patch) if draw_element_numbers: centroid = (np.sum(elverts, axis=1) / elverts.shape[1]) if len(mesh.groups) == 1: el_label = str(iel) else: el_label = "%d:%d" % (igrp, iel) pt.text(centroid[0], centroid[1], el_label, fontsize=17, ha="center", va="center", bbox=dict(facecolor='white', alpha=0.5, lw=0)) if draw_vertex_numbers: for ivert, vert in enumerate(mesh.vertices.T): pt.text(vert[0], vert[1], str(ivert), fontsize=15, ha="center", va="center", color="blue", bbox=dict(facecolor='white', alpha=0.5, lw=0)) if draw_connectivity: def global_iel_to_group_and_iel(global_iel): for igrp, grp in enumerate(mesh.groups): if global_iel < grp.nelements: return grp, global_iel global_iel -= grp.nelements raise ValueError("invalid element nr") cnx = mesh.element_connectivity nb_starts = cnx.neighbors_starts for iel_g in range(mesh.nelements): for nb_iel_g in cnx.neighbors[nb_starts[iel_g]:nb_starts[iel_g+1]]: assert iel_g != nb_iel_g grp, iel = global_iel_to_group_and_iel(iel_g) nb_grp, nb_iel = global_iel_to_group_and_iel(nb_iel_g) elverts = mesh.vertices[:, grp.vertex_indices[iel]] nb_elverts = mesh.vertices[:, nb_grp.vertex_indices[nb_iel]] centroid = (np.sum(elverts, axis=1) / elverts.shape[1]) nb_centroid = (np.sum(nb_elverts, axis=1) / nb_elverts.shape[1]) dx = nb_centroid - centroid start = centroid + 0.15*dx mag = np.max(np.abs(dx)) start += 0.05*(np.random.rand(2)-0.5)*mag dx += 0.05*(np.random.rand(2)-0.5)*mag pt.arrow(start[0], start[1], 0.7*dx[0], 0.7*dx[1], length_includes_head=True, color="green", head_width=1e-2, lw=1e-2) if set_bounding_box: from meshmode.mesh.processing import find_bounding_box lower, upper = find_bounding_box(mesh) pt.xlim([lower[0], upper[0]]) pt.ylim([lower[1], upper[1]])
def run_exterior_stokes( ctx_factory, *, ambient_dim, target_order, qbx_order, resolution, fmm_order=False, # FIXME: FMM is slower than direct evaluation source_ovsmp=None, radius=1.5, mu=1.0, visualize=False, _target_association_tolerance=0.05, _expansions_in_tree_have_extent=True): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) # {{{ geometry if source_ovsmp is None: source_ovsmp = 4 if ambient_dim == 2 else 8 places = {} if ambient_dim == 2: from meshmode.mesh.generation import make_curve_mesh, ellipse mesh = make_curve_mesh(lambda t: radius * ellipse(1.0, t), np.linspace(0.0, 1.0, resolution + 1), target_order) elif ambient_dim == 3: from meshmode.mesh.generation import generate_icosphere mesh = generate_icosphere(radius, target_order + 1, uniform_refinement_rounds=resolution) else: raise ValueError(f"unsupported dimension: {ambient_dim}") pre_density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) from pytential.qbx import QBXLayerPotentialSource qbx = QBXLayerPotentialSource( pre_density_discr, fine_order=source_ovsmp * target_order, qbx_order=qbx_order, fmm_order=fmm_order, target_association_tolerance=_target_association_tolerance, _expansions_in_tree_have_extent=_expansions_in_tree_have_extent) places["source"] = qbx from extra_int_eq_data import make_source_and_target_points point_source, point_target = make_source_and_target_points( side=+1, inner_radius=0.5 * radius, outer_radius=2.0 * radius, ambient_dim=ambient_dim, ) places["point_source"] = point_source places["point_target"] = point_target if visualize: from sumpy.visualization import make_field_plotter_from_bbox from meshmode.mesh.processing import find_bounding_box fplot = make_field_plotter_from_bbox(find_bounding_box(mesh), h=0.1, extend_factor=1.0) mask = np.linalg.norm(fplot.points, ord=2, axis=0) > (radius + 0.25) from pytential.target import PointsTarget plot_target = PointsTarget(fplot.points[:, mask].copy()) places["plot_target"] = plot_target del mask places = GeometryCollection(places, auto_where="source") density_discr = places.get_discretization("source") logger.info("ndofs: %d", density_discr.ndofs) logger.info("nelements: %d", density_discr.mesh.nelements) # }}} # {{{ symbolic sym_normal = sym.make_sym_vector("normal", ambient_dim) sym_mu = sym.var("mu") if ambient_dim == 2: from pytential.symbolic.stokes import HsiaoKressExteriorStokesOperator sym_omega = sym.make_sym_vector("omega", ambient_dim) op = HsiaoKressExteriorStokesOperator(omega=sym_omega) elif ambient_dim == 3: from pytential.symbolic.stokes import HebekerExteriorStokesOperator op = HebekerExteriorStokesOperator() else: assert False sym_sigma = op.get_density_var("sigma") sym_bc = op.get_density_var("bc") sym_op = op.operator(sym_sigma, normal=sym_normal, mu=sym_mu) sym_rhs = op.prepare_rhs(sym_bc, mu=mu) sym_velocity = op.velocity(sym_sigma, normal=sym_normal, mu=sym_mu) sym_source_pot = op.stokeslet.apply(sym_sigma, sym_mu, qbx_forced_limit=None) # }}} # {{{ boundary conditions normal = bind(places, sym.normal(ambient_dim).as_vector())(actx) np.random.seed(42) charges = make_obj_array([ actx.from_numpy(np.random.randn(point_source.ndofs)) for _ in range(ambient_dim) ]) if ambient_dim == 2: total_charge = make_obj_array([actx.np.sum(c) for c in charges]) omega = bind(places, total_charge * sym.Ones())(actx) if ambient_dim == 2: bc_context = {"mu": mu, "omega": omega} op_context = {"mu": mu, "omega": omega, "normal": normal} else: bc_context = {} op_context = {"mu": mu, "normal": normal} bc = bind(places, sym_source_pot, auto_where=("point_source", "source"))(actx, sigma=charges, mu=mu) rhs = bind(places, sym_rhs)(actx, bc=bc, **bc_context) bound_op = bind(places, sym_op) # }}} # {{{ solve from pytential.solve import gmres gmres_tol = 1.0e-9 result = gmres(bound_op.scipy_op(actx, "sigma", np.float64, **op_context), rhs, x0=rhs, tol=gmres_tol, progress=visualize, stall_iterations=0, hard_failure=True) sigma = result.solution # }}} # {{{ check velocity at "point_target" def rnorm2(x, y): y_norm = actx.np.linalg.norm(y.dot(y), ord=2) if y_norm < 1.0e-14: y_norm = 1.0 d = x - y return actx.np.linalg.norm(d.dot(d), ord=2) / y_norm ps_velocity = bind(places, sym_velocity, auto_where=("source", "point_target"))(actx, sigma=sigma, **op_context) ex_velocity = bind(places, sym_source_pot, auto_where=("point_source", "point_target"))(actx, sigma=charges, mu=mu) v_error = rnorm2(ps_velocity, ex_velocity) h_max = bind(places, sym.h_max(ambient_dim))(actx) logger.info("resolution %4d h_max %.5e error %.5e", resolution, h_max, v_error) # }}}} # {{{ visualize if not visualize: return h_max, v_error from meshmode.discretization.visualization import make_visualizer vis = make_visualizer(actx, density_discr, target_order) filename = "stokes_solution_{}d_{}_ovsmp_{}.vtu".format( ambient_dim, resolution, source_ovsmp) vis.write_vtk_file(filename, [ ("density", sigma), ("bc", bc), ("rhs", rhs), ], overwrite=True) # }}} return h_max, v_error
def test_refinement_connection( ctx_getter, refiner_cls, group_factory, mesh_name, dim, mesh_pars, mesh_order, refine_flags, visualize=False): from random import seed seed(13) # Discretization order order = 5 cl_ctx = ctx_getter() queue = cl.CommandQueue(cl_ctx) from meshmode.discretization import Discretization from meshmode.discretization.connection import ( make_refinement_connection, check_connection) from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for mesh_par in mesh_pars: # {{{ get mesh if mesh_name == "circle": assert dim == 1 h = 1 / mesh_par mesh = make_curve_mesh( partial(ellipse, 1), np.linspace(0, 1, mesh_par + 1), order=mesh_order) elif mesh_name == "blob": if mesh_order == 5: pytest.xfail("https://gitlab.tiker.net/inducer/meshmode/issues/2") assert dim == 2 mesh = get_blob_mesh(mesh_par, mesh_order) h = float(mesh_par) elif mesh_name == "warp": from meshmode.mesh.generation import generate_warped_rect_mesh mesh = generate_warped_rect_mesh(dim, order=mesh_order, n=mesh_par) h = 1/mesh_par else: raise ValueError("mesh_name not recognized") # }}} from meshmode.mesh.processing import find_bounding_box mesh_bbox_low, mesh_bbox_high = find_bounding_box(mesh) mesh_ext = mesh_bbox_high-mesh_bbox_low def f(x): result = 1 if mesh_name == "blob": factor = 15 else: factor = 9 for iaxis in range(len(x)): result = result * cl.clmath.sin(factor * (x[iaxis]/mesh_ext[iaxis])) return result discr = Discretization(cl_ctx, mesh, group_factory(order)) refiner = refiner_cls(mesh) flags = refine_flags(mesh) refiner.refine(flags) connection = make_refinement_connection( refiner, discr, group_factory(order)) check_connection(connection) fine_discr = connection.to_discr x = discr.nodes().with_queue(queue) x_fine = fine_discr.nodes().with_queue(queue) f_coarse = f(x) f_interp = connection(queue, f_coarse).with_queue(queue) f_true = f(x_fine).with_queue(queue) if visualize == "dots": import matplotlib.pyplot as plt x = x.get(queue) err = np.array(np.log10( 1e-16 + np.abs((f_interp - f_true).get(queue))), dtype=float) import matplotlib.cm as cm cmap = cm.ScalarMappable(cmap=cm.jet) cmap.set_array(err) plt.scatter(x[0], x[1], c=cmap.to_rgba(err), s=20, cmap=cmap) plt.colorbar(cmap) plt.show() elif visualize == "vtk": from meshmode.discretization.visualization import make_visualizer fine_vis = make_visualizer(queue, fine_discr, mesh_order) fine_vis.write_vtk_file( "refine-fine-%s-%dd-%s.vtu" % (mesh_name, dim, mesh_par), [ ("f_interp", f_interp), ("f_true", f_true), ]) import numpy.linalg as la err = la.norm((f_interp - f_true).get(queue), np.inf) eoc_rec.add_data_point(h, err) order_slack = 0.5 if mesh_name == "blob" and order > 1: order_slack = 1 print(eoc_rec) assert ( eoc_rec.order_estimate() >= order-order_slack or eoc_rec.max_error() < 1e-14)
def main(mesh_name="ellipsoid"): import logging logger = logging.getLogger(__name__) 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 == "ellipsoid": cad_file_name = "geometries/ellipsoid.step" h = 0.6 elif mesh_name == "two-cylinders": cad_file_name = "geometries/two-cylinders-smooth.step" h = 0.4 else: raise ValueError("unknown mesh name: %s" % mesh_name) from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource(cad_file_name), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h], target_unit="MM") from meshmode.mesh.processing import perform_flips # Flip elements--gmsh generates inside-out geometry. mesh = perform_flips(mesh, np.ones(mesh.nelements)) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5 * (bbox_min + bbox_max) bbox_size = max(bbox_max - bbox_min) / 2 logger.info("%d elements" % mesh.nelements) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) qbx = QBXLayerPotentialSource(density_discr, 4 * target_order, qbx_order, fmm_order=qbx_order + 3, target_association_tolerance=0.15) from pytential.target import PointsTarget fplot = FieldPlotter(bbox_center, extent=3.5 * bbox_size, npoints=150) from pytential import GeometryCollection places = GeometryCollection( { "qbx": qbx, "targets": PointsTarget(fplot.points) }, auto_where="qbx") density_discr = places.get_discretization("qbx") nodes = thaw(actx, density_discr.nodes()) angle = actx.np.arctan2(nodes[1], nodes[0]) if k: kernel = HelmholtzKernel(3) else: kernel = LaplaceKernel(3) #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None)) op = sym.D(kernel, sym.var("sigma"), qbx_forced_limit=None) #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None) sigma = actx.np.cos(mode_nr * angle) if 0: from meshmode.dof_array import flatten, unflatten sigma = flatten(0 * angle) from random import randrange for i in range(5): sigma[randrange(len(sigma))] = 1 sigma = unflatten(actx, density_discr, sigma) if isinstance(kernel, HelmholtzKernel): for i, elem in np.ndenumerate(sigma): sigma[i] = elem.astype(np.complex128) fld_in_vol = actx.to_numpy( bind(places, op, auto_where=("qbx", "targets"))(actx, sigma=sigma, k=k)) #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5) fplot.write_vtk_file("layerpot-3d-potential.vts", [("potential", fld_in_vol)]) bdry_normals = bind(places, sym.normal( density_discr.ambient_dim))(actx).as_vector(dtype=object) from meshmode.discretization.visualization import make_visualizer bdry_vis = make_visualizer(actx, density_discr, target_order) bdry_vis.write_vtk_file("layerpot-3d-density.vtu", [ ("sigma", sigma), ("bdry_normals", bdry_normals), ])
case.target_order + 3) bdry_normals = bind(scat_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("source-%s.vtu" % resolution, [ ("j", jxyz), ("rho", rho), ("Einc", inc_field_scat.e), ("Hinc", inc_field_scat.h), ("bdry_normals", bdry_normals), ("e_bc_residual", eh_bc_values[:3]), ("h_bc_residual", eh_bc_values[3]), ]) fplot = make_field_plotter_from_bbox(find_bounding_box( scat_discr.mesh), h=(0.05, 0.05, 0.3), extend_factor=0.3) from pytential.qbx import QBXTargetAssociationFailedException qbx_tgt_tol = qbx.copy(target_association_tolerance=0.2) fplot_tgt = PointsTarget(cl.array.to_device(queue, fplot.points)) try: fplot_repr = eval_repr_at(fplot_tgt, source=qbx_tgt_tol) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [("failed_targets", e.failed_target_flags.get(queue))]) raise
def run_int_eq_test(cl_ctx, queue, case, resolution, visualize): mesh = case.get_mesh(resolution, case.target_order) print("%d elements" % mesh.nelements) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory pre_density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(case.target_order)) source_order = 4*case.target_order refiner_extra_kwargs = {} qbx_lpot_kwargs = {} if case.fmm_backend is None: qbx_lpot_kwargs["fmm_order"] = False else: if hasattr(case, "fmm_tol"): from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder qbx_lpot_kwargs["fmm_level_to_order"] = SimpleExpansionOrderFinder( case.fmm_tol) elif hasattr(case, "fmm_order"): qbx_lpot_kwargs["fmm_order"] = case.fmm_order else: qbx_lpot_kwargs["fmm_order"] = case.qbx_order + 5 qbx = QBXLayerPotentialSource( pre_density_discr, fine_order=source_order, qbx_order=case.qbx_order, _box_extent_norm=getattr(case, "box_extent_norm", None), _from_sep_smaller_crit=getattr(case, "from_sep_smaller_crit", None), _from_sep_smaller_min_nsources_cumul=30, fmm_backend=case.fmm_backend, **qbx_lpot_kwargs) if case.use_refinement: if case.k != 0 and getattr(case, "refine_on_helmholtz_k", True): refiner_extra_kwargs["kernel_length_scale"] = 5/case.k if hasattr(case, "scaled_max_curvature_threshold"): refiner_extra_kwargs["_scaled_max_curvature_threshold"] = \ case.scaled_max_curvature_threshold if hasattr(case, "expansion_disturbance_tolerance"): refiner_extra_kwargs["_expansion_disturbance_tolerance"] = \ case.expansion_disturbance_tolerance if hasattr(case, "refinement_maxiter"): refiner_extra_kwargs["maxiter"] = case.refinement_maxiter #refiner_extra_kwargs["visualize"] = True print("%d elements before refinement" % pre_density_discr.mesh.nelements) qbx, _ = qbx.with_refinement(**refiner_extra_kwargs) print("%d stage-1 elements after refinement" % qbx.density_discr.mesh.nelements) print("%d stage-2 elements after refinement" % qbx.stage2_density_discr.mesh.nelements) print("quad stage-2 elements have %d nodes" % qbx.quad_stage2_density_discr.groups[0].nunit_nodes) density_discr = qbx.density_discr if hasattr(case, "visualize_geometry") and case.visualize_geometry: bdry_normals = bind( density_discr, sym.normal(mesh.ambient_dim) )(queue).as_vector(dtype=object) bdry_vis = make_visualizer(queue, density_discr, case.target_order) bdry_vis.write_vtk_file("geometry.vtu", [ ("normals", bdry_normals) ]) # {{{ plot geometry if 0: if mesh.ambient_dim == 2: # show geometry, centers, normals nodes_h = density_discr.nodes().get(queue=queue) pt.plot(nodes_h[0], nodes_h[1], "x-") normal = bind(density_discr, sym.normal(2))(queue).as_vector(np.object) pt.quiver(nodes_h[0], nodes_h[1], normal[0].get(queue), normal[1].get(queue)) pt.gca().set_aspect("equal") pt.show() elif mesh.ambient_dim == 3: bdry_vis = make_visualizer(queue, density_discr, case.target_order+3) bdry_normals = bind(density_discr, sym.normal(3))(queue)\ .as_vector(dtype=object) bdry_vis.write_vtk_file("pre-solve-source-%s.vtu" % resolution, [ ("bdry_normals", bdry_normals), ]) else: raise ValueError("invalid mesh dim") # }}} # {{{ set up operator from pytential.symbolic.pde.scalar import ( DirichletOperator, NeumannOperator) from sumpy.kernel import LaplaceKernel, HelmholtzKernel if case.k: knl = HelmholtzKernel(mesh.ambient_dim) knl_kwargs = {"k": sym.var("k")} concrete_knl_kwargs = {"k": case.k} else: knl = LaplaceKernel(mesh.ambient_dim) knl_kwargs = {} concrete_knl_kwargs = {} if knl.is_complex_valued: dtype = np.complex128 else: dtype = np.float64 loc_sign = +1 if case.prob_side in [+1, "scat"] else -1 if case.bc_type == "dirichlet": op = DirichletOperator(knl, loc_sign, use_l2_weighting=True, kernel_arguments=knl_kwargs) elif case.bc_type == "neumann": op = NeumannOperator(knl, loc_sign, use_l2_weighting=True, use_improved_operator=False, kernel_arguments=knl_kwargs) else: assert False op_u = op.operator(sym.var("u")) # }}} # {{{ set up test data if case.prob_side == -1: test_src_geo_radius = case.outer_radius test_tgt_geo_radius = case.inner_radius elif case.prob_side == +1: test_src_geo_radius = case.inner_radius test_tgt_geo_radius = case.outer_radius elif case.prob_side == "scat": test_src_geo_radius = case.outer_radius test_tgt_geo_radius = case.outer_radius else: raise ValueError("unknown problem_side") point_sources = make_circular_point_group( mesh.ambient_dim, 10, test_src_geo_radius, func=lambda x: x**1.5) test_targets = make_circular_point_group( mesh.ambient_dim, 20, test_tgt_geo_radius) np.random.seed(22) source_charges = np.random.randn(point_sources.shape[1]) source_charges[-1] = -np.sum(source_charges[:-1]) source_charges = source_charges.astype(dtype) assert np.sum(source_charges) < 1e-15 source_charges_dev = cl.array.to_device(queue, source_charges) # }}} # {{{ establish BCs from pytential.source import PointPotentialSource from pytential.target import PointsTarget point_source = PointPotentialSource(cl_ctx, point_sources) pot_src = sym.IntG( # FIXME: qbx_forced_limit--really? knl, sym.var("charges"), qbx_forced_limit=None, **knl_kwargs) test_direct = bind((point_source, PointsTarget(test_targets)), pot_src)( queue, charges=source_charges_dev, **concrete_knl_kwargs) if case.bc_type == "dirichlet": bc = bind((point_source, density_discr), pot_src)( queue, charges=source_charges_dev, **concrete_knl_kwargs) elif case.bc_type == "neumann": bc = bind( (point_source, density_discr), sym.normal_derivative( qbx.ambient_dim, pot_src, where=sym.DEFAULT_TARGET) )(queue, charges=source_charges_dev, **concrete_knl_kwargs) # }}} # {{{ solve bound_op = bind(qbx, op_u) rhs = bind(density_discr, op.prepare_rhs(sym.var("bc")))(queue, bc=bc) try: from pytential.solve import gmres gmres_result = gmres( bound_op.scipy_op(queue, "u", dtype, **concrete_knl_kwargs), rhs, tol=case.gmres_tol, progress=True, hard_failure=True, stall_iterations=50, no_progress_factor=1.05) except QBXTargetAssociationFailedException as e: bdry_vis = make_visualizer(queue, density_discr, case.target_order+3) bdry_vis.write_vtk_file("failed-targets-%s.vtu" % resolution, [ ("failed_targets", e.failed_target_flags), ]) raise print("gmres state:", gmres_result.state) weighted_u = gmres_result.solution # }}} # {{{ build matrix for spectrum check if 0: from sumpy.tools import build_matrix mat = build_matrix( bound_op.scipy_op( queue, arg_name="u", dtype=dtype, k=case.k)) w, v = la.eig(mat) if 0: pt.imshow(np.log10(1e-20+np.abs(mat))) pt.colorbar() pt.show() #assert abs(s[-1]) < 1e-13, "h #assert abs(s[-2]) > 1e-7 #from pudb import set_trace; set_trace() # }}} if case.prob_side != "scat": # {{{ error check points_target = PointsTarget(test_targets) bound_tgt_op = bind((qbx, points_target), op.representation(sym.var("u"))) test_via_bdry = bound_tgt_op(queue, u=weighted_u, k=case.k) err = test_via_bdry - test_direct err = err.get() test_direct = test_direct.get() test_via_bdry = test_via_bdry.get() # {{{ remove effect of net source charge if case.k == 0 and case.bc_type == "neumann" and loc_sign == -1: # remove constant offset in interior Laplace Neumann error tgt_ones = np.ones_like(test_direct) tgt_ones = tgt_ones/la.norm(tgt_ones) err = err - np.vdot(tgt_ones, err)*tgt_ones # }}} rel_err_2 = la.norm(err)/la.norm(test_direct) rel_err_inf = la.norm(err, np.inf)/la.norm(test_direct, np.inf) # }}} print("rel_err_2: %g rel_err_inf: %g" % (rel_err_2, rel_err_inf)) else: rel_err_2 = None rel_err_inf = None # {{{ test gradient if case.check_gradient and case.prob_side != "scat": bound_grad_op = bind((qbx, points_target), op.representation( sym.var("u"), map_potentials=lambda pot: sym.grad(mesh.ambient_dim, pot), qbx_forced_limit=None)) #print(bound_t_deriv_op.code) grad_from_src = bound_grad_op( queue, u=weighted_u, **concrete_knl_kwargs) grad_ref = (bind( (point_source, points_target), sym.grad(mesh.ambient_dim, pot_src) )(queue, charges=source_charges_dev, **concrete_knl_kwargs) ) grad_err = (grad_from_src - grad_ref) rel_grad_err_inf = ( la.norm(grad_err[0].get(), np.inf) / la.norm(grad_ref[0].get(), np.inf)) print("rel_grad_err_inf: %g" % rel_grad_err_inf) # }}} # {{{ test tangential derivative if case.check_tangential_deriv and case.prob_side != "scat": bound_t_deriv_op = bind(qbx, op.representation( sym.var("u"), map_potentials=lambda pot: sym.tangential_derivative(2, pot), qbx_forced_limit=loc_sign)) #print(bound_t_deriv_op.code) tang_deriv_from_src = bound_t_deriv_op( queue, u=weighted_u, **concrete_knl_kwargs).as_scalar().get() tang_deriv_ref = (bind( (point_source, density_discr), sym.tangential_derivative(2, pot_src) )(queue, charges=source_charges_dev, **concrete_knl_kwargs) .as_scalar().get()) if 0: pt.plot(tang_deriv_ref.real) pt.plot(tang_deriv_from_src.real) pt.show() td_err = (tang_deriv_from_src - tang_deriv_ref) rel_td_err_inf = la.norm(td_err, np.inf)/la.norm(tang_deriv_ref, np.inf) print("rel_td_err_inf: %g" % rel_td_err_inf) else: rel_td_err_inf = None # }}} # {{{ any-D file plotting if visualize: bdry_vis = make_visualizer(queue, density_discr, case.target_order+3) bdry_normals = bind(density_discr, sym.normal(qbx.ambient_dim))(queue)\ .as_vector(dtype=object) sym_sqrt_j = sym.sqrt_jac_q_weight(density_discr.ambient_dim) u = bind(density_discr, sym.var("u")/sym_sqrt_j)(queue, u=weighted_u) bdry_vis.write_vtk_file("source-%s.vtu" % resolution, [ ("u", u), ("bc", bc), #("bdry_normals", bdry_normals), ]) from sumpy.visualization import make_field_plotter_from_bbox # noqa from meshmode.mesh.processing import find_bounding_box vis_grid_spacing = (0.1, 0.1, 0.1)[:qbx.ambient_dim] if hasattr(case, "vis_grid_spacing"): vis_grid_spacing = case.vis_grid_spacing vis_extend_factor = 0.2 if hasattr(case, "vis_extend_factor"): vis_grid_spacing = case.vis_grid_spacing fplot = make_field_plotter_from_bbox( find_bounding_box(mesh), h=vis_grid_spacing, extend_factor=vis_extend_factor) qbx_tgt_tol = qbx.copy(target_association_tolerance=0.15) from pytential.target import PointsTarget try: solved_pot = bind( (qbx_tgt_tol, PointsTarget(fplot.points)), op.representation(sym.var("u")) )(queue, u=weighted_u, k=case.k) except QBXTargetAssociationFailedException as e: fplot.write_vtk_file( "failed-targets.vts", [ ("failed_targets", e.failed_target_flags.get(queue)) ]) raise from sumpy.kernel import LaplaceKernel ones_density = density_discr.zeros(queue) ones_density.fill(1) indicator = bind( (qbx_tgt_tol, PointsTarget(fplot.points)), -sym.D(LaplaceKernel(density_discr.ambient_dim), sym.var("sigma"), qbx_forced_limit=None))( queue, sigma=ones_density).get() solved_pot = solved_pot.get() true_pot = bind((point_source, PointsTarget(fplot.points)), pot_src)( queue, charges=source_charges_dev, **concrete_knl_kwargs).get() #fplot.show_scalar_in_mayavi(solved_pot.real, max_val=5) if case.prob_side == "scat": fplot.write_vtk_file( "potential-%s.vts" % resolution, [ ("pot_scattered", solved_pot), ("pot_incoming", -true_pot), ("indicator", indicator), ] ) else: fplot.write_vtk_file( "potential-%s.vts" % resolution, [ ("solved_pot", solved_pot), ("true_pot", true_pot), ("indicator", indicator), ] ) # }}} class Result(Record): pass return Result( h_max=qbx.h_max, rel_err_2=rel_err_2, rel_err_inf=rel_err_inf, rel_td_err_inf=rel_td_err_inf, gmres_result=gmres_result)
h = 0.4 k = 0 if k: kernel = HelmholtzKernel("k") else: kernel = LaplaceKernel() #kernel = OneKernel() from meshmode.mesh.io import generate_gmsh, FileSource mesh = generate_gmsh( FileSource("molecule.step"), 2, order=2, other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h]) from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) bbox_center = 0.5*(bbox_min+bbox_max) bbox_size = max(bbox_max-bbox_min) / 2 logger.info("%d elements" % mesh.nelements) from pytential.qbx import QBXLayerPotentialSource from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory density_discr = Discretization( cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order)) qbx = QBXLayerPotentialSource(density_discr, 4*target_order, qbx_order, fmm_order=qbx_order)
def test_refinement_connection(actx_factory, refiner_cls, group_factory, mesh_name, dim, mesh_pars, mesh_order, refine_flags, visualize=False): group_cls = group_factory.mesh_group_class if issubclass(group_cls, TensorProductElementGroup): if mesh_name in ["circle", "blob"]: pytest.skip("mesh does not have tensor product support") from random import seed seed(13) actx = actx_factory() # discretization order order = 5 from meshmode.discretization import Discretization from meshmode.discretization.connection import (make_refinement_connection, check_connection) from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for mesh_par in mesh_pars: # {{{ get mesh if mesh_name == "circle": assert dim == 1 h = 1 / mesh_par mesh = make_curve_mesh(partial(ellipse, 1), np.linspace(0, 1, mesh_par + 1), order=mesh_order) elif mesh_name == "blob": if mesh_order == 5: pytest.xfail( "https://gitlab.tiker.net/inducer/meshmode/issues/2") assert dim == 2 mesh = get_blob_mesh(mesh_par, mesh_order) h = float(mesh_par) elif mesh_name == "warp": mesh = mgen.generate_warped_rect_mesh(dim, order=mesh_order, n=mesh_par, group_cls=group_cls) h = 1 / mesh_par else: raise ValueError("mesh_name not recognized") # }}} from meshmode.mesh.processing import find_bounding_box mesh_bbox_low, mesh_bbox_high = find_bounding_box(mesh) mesh_ext = mesh_bbox_high - mesh_bbox_low def f(x): result = 1 if mesh_name == "blob": factor = 15 else: factor = 9 for iaxis in range(len(x)): result = result * actx.np.sin(factor * (x[iaxis] / mesh_ext[iaxis])) return result discr = Discretization(actx, mesh, group_factory(order)) refiner = refiner_cls(mesh) flags = refine_flags(mesh) refiner.refine(flags) connection = make_refinement_connection(actx, refiner, discr, group_factory(order)) check_connection(actx, connection) fine_discr = connection.to_discr x = thaw(actx, discr.nodes()) x_fine = thaw(actx, fine_discr.nodes()) f_coarse = f(x) f_interp = connection(f_coarse) f_true = f(x_fine) if visualize == "dots": import matplotlib.pyplot as plt x = x.get(actx.queue) err = np.array( np.log10(1e-16 + np.abs((f_interp - f_true).get(actx.queue))), dtype=float) import matplotlib.cm as cm cmap = cm.ScalarMappable(cmap=cm.jet) cmap.set_array(err) plt.scatter(x[0], x[1], c=cmap.to_rgba(err), s=20, cmap=cmap) plt.colorbar(cmap) plt.show() elif visualize == "vtk": from meshmode.discretization.visualization import make_visualizer fine_vis = make_visualizer(actx, fine_discr, mesh_order) fine_vis.write_vtk_file( "refine-fine-%s-%dd-%s.vtu" % (mesh_name, dim, mesh_par), [ ("f_interp", f_interp), ("f_true", f_true), ]) err = actx.np.linalg.norm(f_interp - f_true, np.inf) eoc_rec.add_data_point(h, err) order_slack = 0.5 if mesh_name == "blob" and order > 1: order_slack = 1 print(eoc_rec) assert (eoc_rec.order_estimate() >= order - order_slack or eoc_rec.max_error() < 1e-14)
def check_nodal_adj_against_geometry(mesh, tol=1e-12): def group_and_iel_to_global_iel(igrp, iel): return mesh.groups[igrp].element_nr_base + iel logger.debug("nodal adj test: tree build") from meshmode.mesh.tools import make_element_lookup_tree tree = make_element_lookup_tree(mesh, eps=tol) logger.debug("nodal adj test: tree build done") from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) nadj = mesh.nodal_adjacency nvertices_per_element = len(mesh.groups[0].vertex_indices[0]) connected_to_element_geometry = [set() for i in range(mesh.nelements)] connected_to_element_connectivity = [set() for i in range(mesh.nelements)] for igrp, grp in enumerate(mesh.groups): for iel_grp in range(grp.nelements): iel_g = group_and_iel_to_global_iel(igrp, iel_grp) nb_starts = nadj.neighbors_starts for nb_iel_g in nadj.neighbors[nb_starts[iel_g]:nb_starts[iel_g+1]]: connected_to_element_connectivity[iel_g].add(nb_iel_g) for vertex_index in grp.vertex_indices[iel_grp]: vertex = mesh.vertices[:, vertex_index] # check which elements touch this vertex for nearby_igrp, nearby_iel in tree.generate_matches(vertex): if nearby_igrp == igrp and nearby_iel == iel_grp: continue nearby_grp = mesh.groups[nearby_igrp] nearby_origin_vertex = mesh.vertices[ :, nearby_grp.vertex_indices[nearby_iel][0]] # noqa transformation = np.empty( (len(mesh.vertices), nvertices_per_element-1)) vertex_transformed = vertex - nearby_origin_vertex for inearby_vertex_index, nearby_vertex_index in enumerate( nearby_grp.vertex_indices[nearby_iel][1:]): nearby_vertex = mesh.vertices[:, nearby_vertex_index] transformation[:, inearby_vertex_index] = \ nearby_vertex - nearby_origin_vertex bary_coord, residual = \ np.linalg.lstsq(transformation, vertex_transformed)[0:2] is_in_element_span = ( residual.size == 0 or np.linalg.norm(vertex_transformed) == 0 or (np.linalg.norm(residual) / np.linalg.norm(vertex_transformed)) <= tol) is_connected = ( is_in_element_span and np.sum(bary_coord) <= 1+tol and (bary_coord >= -tol).all()) el1 = group_and_iel_to_global_iel(nearby_igrp, nearby_iel) el2 = group_and_iel_to_global_iel(igrp, iel_grp) if is_connected: connected_to_element_geometry[el1].add(el2) connected_to_element_geometry[el2].add(el1) assert is_symmetric(connected_to_element_connectivity, debug=True) # The geometric adjacency relation isn't necessary symmetric: # # /| # / | # / |\ # B \ |/ A # \ | # \| # # Element A will see element B (its vertices are near B) but not the other # way around. assert connected_to_element_geometry == connected_to_element_connectivity
def check_nodal_adj_against_geometry(mesh, tol=1e-12): def group_and_iel_to_global_iel(igrp, iel): return mesh.groups[igrp].element_nr_base + iel logger.debug("nodal adj test: tree build") from meshmode.mesh.tools import make_element_lookup_tree tree = make_element_lookup_tree(mesh, eps=tol) logger.debug("nodal adj test: tree build done") from meshmode.mesh.processing import find_bounding_box bbox_min, bbox_max = find_bounding_box(mesh) nadj = mesh.nodal_adjacency nvertices_per_element = len(mesh.groups[0].vertex_indices[0]) connected_to_element_geometry = [set() for i in range(mesh.nelements)] connected_to_element_connectivity = [set() for i in range(mesh.nelements)] for igrp, grp in enumerate(mesh.groups): for iel_grp in range(grp.nelements): iel_g = group_and_iel_to_global_iel(igrp, iel_grp) nb_starts = nadj.neighbors_starts for nb_iel_g in nadj.neighbors[nb_starts[iel_g]:nb_starts[iel_g + 1]]: connected_to_element_connectivity[iel_g].add(nb_iel_g) for vertex_index in grp.vertex_indices[iel_grp]: vertex = mesh.vertices[:, vertex_index] # check which elements touch this vertex for nearby_igrp, nearby_iel in tree.generate_matches(vertex): if nearby_igrp == igrp and nearby_iel == iel_grp: continue nearby_grp = mesh.groups[nearby_igrp] nearby_origin_vertex = mesh.vertices[:, nearby_grp. vertex_indices[ nearby_iel] [0]] # noqa transformation = np.empty( (len(mesh.vertices), nvertices_per_element - 1)) vertex_transformed = vertex - nearby_origin_vertex for inearby_vertex_index, nearby_vertex_index in enumerate( nearby_grp.vertex_indices[nearby_iel][1:]): nearby_vertex = mesh.vertices[:, nearby_vertex_index] transformation[:, inearby_vertex_index] = \ nearby_vertex - nearby_origin_vertex bary_coord, residual = \ np.linalg.lstsq(transformation, vertex_transformed)[0:2] is_in_element_span = ( residual.size == 0 or np.linalg.norm(vertex_transformed) == 0 or (np.linalg.norm(residual) / np.linalg.norm(vertex_transformed)) <= tol) is_connected = (is_in_element_span and np.sum(bary_coord) <= 1 + tol and (bary_coord >= -tol).all()) el1 = group_and_iel_to_global_iel(nearby_igrp, nearby_iel) el2 = group_and_iel_to_global_iel(igrp, iel_grp) if is_connected: connected_to_element_geometry[el1].add(el2) connected_to_element_geometry[el2].add(el1) assert is_symmetric(connected_to_element_connectivity, debug=True) # The geometric adjacency relation isn't necessary symmetric: # # /| # / | # / |\ # B \ |/ A # \ | # \| # # Element A will see element B (its vertices are near B) but not the other # way around. assert connected_to_element_geometry == connected_to_element_connectivity
InterpolatoryQuadratureSimplexGroupFactory(case.target_order)) places.update({ sym.DEFAULT_SOURCE: qbx, sym.DEFAULT_TARGET: qbx.density_discr, "test_source": test_source, "scat_discr": scat_discr, "obs_discr": obs_discr, "patch_target": calc_patch_tgt, }) if visualize: qbx_tgt_tol = qbx.copy(target_association_tolerance=0.2) fplot = make_field_plotter_from_bbox( find_bounding_box(scat_discr.mesh), h=(0.05, 0.05, 0.3), extend_factor=0.3) fplot_tgt = PointsTarget(actx.from_numpy(fplot.points)) places.update({ "qbx_target_tol": qbx_tgt_tol, "plot_targets": fplot_tgt, }) from pytential import GeometryCollection places = GeometryCollection(places) density_discr = places.get_discretization(places.auto_source.geometry) # {{{ system solve h_max = actx.to_numpy(