def test_surface_mass_operator_inverse(actx_factory, name): actx = actx_factory() # {{{ cases if name == "2-1-ellipse": from mesh_data import EllipseMeshBuilder builder = EllipseMeshBuilder(radius=3.1, aspect_ratio=2.0) elif name == "spheroid": from mesh_data import SpheroidMeshBuilder builder = SpheroidMeshBuilder() else: raise ValueError("unknown geometry name: %s" % name) # }}} # {{{ convergence from pytools.convergence import EOCRecorder eoc = EOCRecorder() for resolution in builder.resolutions: mesh = builder.get_mesh(resolution, builder.mesh_order) discr = DiscretizationCollection(actx, mesh, order=builder.order) volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) logger.info("nelements: %d", volume_discr.mesh.nelements) # {{{ compute inverse mass dd = dof_desc.DD_VOLUME sym_f = sym.cos(4.0 * sym.nodes(mesh.ambient_dim, dd)[0]) sym_op = sym.InverseMassOperator(dd, dd)(sym.MassOperator(dd, dd)( sym.var("f"))) f = bind(discr, sym_f)(actx) f_inv = bind(discr, sym_op)(actx, f=f) inv_error = bind( discr, sym.norm(2, sym.var("x") - sym.var("y")) / sym.norm(2, sym.var("y")))( actx, x=f_inv, y=f) # }}} h_max = bind( discr, sym.h_max_from_volume(discr.ambient_dim, dim=discr.dim, dd=dd))(actx) eoc.add_data_point(h_max, inv_error) # }}} logger.info("inverse mass error\n%s", str(eoc)) # NOTE: both cases give 1.0e-16-ish at the moment, but just to be on the # safe side, choose a slightly larger tolerance assert eoc.max_error() < 1.0e-14
def test_1d_mass_mat_trig(ctx_factory): """Check the integral of some trig functions on an interval using the mass matrix """ cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-4 * np.pi, ), b=(9 * np.pi, ), n=(17, ), order=1) discr = DGDiscretizationWithBoundaries(cl_ctx, mesh, order=8) x = sym.nodes(1) f = bind(discr, sym.cos(x[0])**2)(queue) ones = bind(discr, sym.Ones(sym.DD_VOLUME))(queue) mass_op = bind(discr, sym.MassOperator()(sym.var("f"))) num_integral_1 = np.dot(ones.get(), mass_op(queue, f=f)) num_integral_2 = np.dot(f.get(), mass_op(queue, f=ones)) num_integral_3 = bind(discr, sym.integral(sym.var("f")))(queue, f=f) true_integral = 13 * np.pi / 2 err_1 = abs(num_integral_1 - true_integral) err_2 = abs(num_integral_2 - true_integral) err_3 = abs(num_integral_3 - true_integral) assert err_1 < 1e-10 assert err_2 < 1e-10 assert err_3 < 1e-10
def get_rectangular_cavity_mode(E_0, mode_indices): # noqa: N803 """A rectangular TM cavity mode for a rectangle / cube with one corner at the origin and the other at (1,1[,1]).""" dims = len(mode_indices) if dims != 2 and dims != 3: raise ValueError("Improper mode_indices dimensions") import numpy factors = [n * numpy.pi for n in mode_indices] kx, ky = factors[0:2] if dims == 3: kz = factors[2] omega = numpy.sqrt(sum(f**2 for f in factors)) nodes = sym.nodes(dims) x = nodes[0] y = nodes[1] if dims == 3: z = nodes[2] sx = sym.sin(kx * x) cx = sym.cos(kx * x) sy = sym.sin(ky * y) cy = sym.cos(ky * y) if dims == 3: sz = sym.sin(kz * z) cz = sym.cos(kz * z) if dims == 2: tfac = sym.ScalarVariable("t") * omega result = flat_obj_array( 0, 0, sym.sin(kx * x) * sym.sin(ky * y) * sym.cos(tfac), # ez -ky * sym.sin(kx * x) * sym.cos(ky * y) * sym.sin(tfac) / omega, # hx kx * sym.cos(kx * x) * sym.sin(ky * y) * sym.sin(tfac) / omega, # hy 0, ) else: tdep = sym.exp(-1j * omega * sym.ScalarVariable("t")) gamma_squared = ky**2 + kx**2 result = flat_obj_array( -kx * kz * E_0 * cx * sy * sz * tdep / gamma_squared, # ex -ky * kz * E_0 * sx * cy * sz * tdep / gamma_squared, # ey E_0 * sx * sy * cz * tdep, # ez -1j * omega * ky * E_0 * sx * cy * cz * tdep / gamma_squared, # hx 1j * omega * kx * E_0 * cx * sy * cz * tdep / gamma_squared, 0, ) return result
def test_tri_diff_mat(ctx_factory, dim, order=4): """Check differentiation matrix along the coordinate axes on a disk Uses sines as the function to differentiate. """ cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) from meshmode.mesh.generation import generate_regular_rect_mesh from pytools.convergence import EOCRecorder axis_eoc_recs = [EOCRecorder() for axis in range(dim)] for n in [10, 20]: mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim, b=(0.5, ) * dim, n=(n, ) * dim, order=4) discr = DGDiscretizationWithBoundaries(actx, mesh, order=4) nabla = sym.nabla(dim) for axis in range(dim): x = sym.nodes(dim) f = bind(discr, sym.sin(3 * x[axis]))(actx) df = bind(discr, 3 * sym.cos(3 * x[axis]))(actx) sym_op = nabla[axis](sym.var("f")) bound_op = bind(discr, sym_op) df_num = bound_op(f=f) linf_error = flat_norm(df_num - df, np.Inf) axis_eoc_recs[axis].add_data_point(1 / n, linf_error) for axis, eoc_rec in enumerate(axis_eoc_recs): logger.info("axis %d\n%s", axis, eoc_rec) assert eoc_rec.order_estimate() >= order
def test_tri_diff_mat(actx_factory, dim, order=4): """Check differentiation matrix along the coordinate axes on a disk Uses sines as the function to differentiate. """ actx = actx_factory() from pytools.convergence import EOCRecorder axis_eoc_recs = [EOCRecorder() for axis in range(dim)] for n in [4, 8, 16]: mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dim, b=(0.5, ) * dim, nelements_per_axis=(n, ) * dim, order=4) discr = DiscretizationCollection(actx, mesh, order=4) nabla = sym.nabla(dim) for axis in range(dim): x = sym.nodes(dim) f = bind(discr, sym.sin(3 * x[axis]))(actx) df = bind(discr, 3 * sym.cos(3 * x[axis]))(actx) sym_op = nabla[axis](sym.var("f")) bound_op = bind(discr, sym_op) df_num = bound_op(f=f) linf_error = actx.np.linalg.norm(df_num - df, ord=np.inf) axis_eoc_recs[axis].add_data_point(1 / n, linf_error) for axis, eoc_rec in enumerate(axis_eoc_recs): logger.info("axis %d\n%s", axis, eoc_rec) assert eoc_rec.order_estimate() > order - 0.25
def test_mass_mat_trig(ctx_factory, ambient_dim, quad_tag): """Check the integral of some trig functions on an interval using the mass matrix. """ cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) nelements = 17 order = 4 a = -4.0 * np.pi b = +9.0 * np.pi true_integral = 13 * np.pi / 2 * (b - a)**(ambient_dim - 1) from meshmode.discretization.poly_element import QuadratureSimplexGroupFactory dd_quad = sym.DOFDesc(sym.DTAG_VOLUME_ALL, quad_tag) if quad_tag is sym.QTAG_NONE: quad_tag_to_group_factory = {} else: quad_tag_to_group_factory = { quad_tag: QuadratureSimplexGroupFactory(order=2 * order) } from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(a, ) * ambient_dim, b=(b, ) * ambient_dim, n=(nelements, ) * ambient_dim, order=1) discr = DGDiscretizationWithBoundaries( actx, mesh, order=order, quad_tag_to_group_factory=quad_tag_to_group_factory) def _get_variables_on(dd): sym_f = sym.var("f", dd=dd) sym_x = sym.nodes(ambient_dim, dd=dd) sym_ones = sym.Ones(dd) return sym_f, sym_x, sym_ones sym_f, sym_x, sym_ones = _get_variables_on(sym.DD_VOLUME) f_volm = actx.to_numpy(flatten(bind(discr, sym.cos(sym_x[0])**2)(actx))) ones_volm = actx.to_numpy(flatten(bind(discr, sym_ones)(actx))) sym_f, sym_x, sym_ones = _get_variables_on(dd_quad) f_quad = bind(discr, sym.cos(sym_x[0])**2)(actx) ones_quad = bind(discr, sym_ones)(actx) mass_op = bind(discr, sym.MassOperator(dd_quad, sym.DD_VOLUME)(sym_f)) num_integral_1 = np.dot(ones_volm, actx.to_numpy(flatten(mass_op(f=f_quad)))) err_1 = abs(num_integral_1 - true_integral) assert err_1 < 1e-9, err_1 num_integral_2 = np.dot(f_volm, actx.to_numpy(flatten(mass_op(f=ones_quad)))) err_2 = abs(num_integral_2 - true_integral) assert err_2 < 1.0e-9, err_2 if quad_tag is sym.QTAG_NONE: # NOTE: `integral` always makes a square mass matrix and # `QuadratureSimplexGroupFactory` does not have a `mass_matrix` method. num_integral_3 = bind(discr, sym.integral(sym_f, dd=dd_quad))(f=f_quad) err_3 = abs(num_integral_3 - true_integral) assert err_3 < 5.0e-10, err_3
def f(x): return flat_obj_array( sym.sin(3 * x[0]) + sym.cos(3 * x[1]), sym.sin(2 * x[0]) + sym.cos(x[1]))
def f(x): return sym.join_fields( sym.sin(3 * x[0]) + sym.cos(3 * x[1]), sym.sin(2 * x[0]) + sym.cos(x[1]))
def test_mass_mat_trig(actx_factory, ambient_dim, discr_tag): """Check the integral of some trig functions on an interval using the mass matrix. """ actx = actx_factory() nel_1d = 16 order = 4 a = -4.0 * np.pi b = +9.0 * np.pi true_integral = 13 * np.pi / 2 * (b - a)**(ambient_dim - 1) from meshmode.discretization.poly_element import QuadratureSimplexGroupFactory dd_quad = dof_desc.DOFDesc(dof_desc.DTAG_VOLUME_ALL, discr_tag) if discr_tag is dof_desc.DISCR_TAG_BASE: discr_tag_to_group_factory = {} else: discr_tag_to_group_factory = { discr_tag: QuadratureSimplexGroupFactory(order=2 * order) } mesh = mgen.generate_regular_rect_mesh(a=(a, ) * ambient_dim, b=(b, ) * ambient_dim, nelements_per_axis=(nel_1d, ) * ambient_dim, order=1) discr = DiscretizationCollection( actx, mesh, order=order, discr_tag_to_group_factory=discr_tag_to_group_factory) def _get_variables_on(dd): sym_f = sym.var("f", dd=dd) sym_x = sym.nodes(ambient_dim, dd=dd) sym_ones = sym.Ones(dd) return sym_f, sym_x, sym_ones sym_f, sym_x, sym_ones = _get_variables_on(dof_desc.DD_VOLUME) f_volm = actx.to_numpy(flatten(bind(discr, sym.cos(sym_x[0])**2)(actx))) ones_volm = actx.to_numpy(flatten(bind(discr, sym_ones)(actx))) sym_f, sym_x, sym_ones = _get_variables_on(dd_quad) f_quad = bind(discr, sym.cos(sym_x[0])**2)(actx) ones_quad = bind(discr, sym_ones)(actx) mass_op = bind(discr, sym.MassOperator(dd_quad, dof_desc.DD_VOLUME)(sym_f)) num_integral_1 = np.dot(ones_volm, actx.to_numpy(flatten(mass_op(f=f_quad)))) err_1 = abs(num_integral_1 - true_integral) assert err_1 < 2e-9, err_1 num_integral_2 = np.dot(f_volm, actx.to_numpy(flatten(mass_op(f=ones_quad)))) err_2 = abs(num_integral_2 - true_integral) assert err_2 < 2e-9, err_2 if discr_tag is dof_desc.DISCR_TAG_BASE: # NOTE: `integral` always makes a square mass matrix and # `QuadratureSimplexGroupFactory` does not have a `mass_matrix` method. num_integral_3 = bind(discr, sym.integral(sym_f, dd=dd_quad))(f=f_quad) err_3 = abs(num_integral_3 - true_integral) assert err_3 < 5.0e-10, err_3
def f(x): return flat_obj_array( sym.sin(3 * x[1]) + sym.cos(3 * x[0]) + 1.0, sym.sin(2 * x[0]) + sym.cos(x[1]), 3.0 * sym.cos(x[0] / 2) + sym.cos(x[1]), )[:ambient_dim]