Beispiel #1
0
def warp_factor(n, output_nodes, scaled=True):
    """Compute warp function at order *n* and evaluate it at
    the nodes *output_nodes*.
    """

    from modepy.quadrature.jacobi_gauss import legendre_gauss_lobatto_nodes

    warped_nodes = legendre_gauss_lobatto_nodes(n)
    equi_nodes = np.linspace(-1, 1, n+1)

    from modepy.matrices import vandermonde
    from modepy.modes import simplex_onb

    basis = simplex_onb(1, n)
    Veq = vandermonde(basis, equi_nodes)  # noqa

    # create interpolator from equi_nodes to output_nodes
    eq_to_out = la.solve(Veq.T, vandermonde(basis, output_nodes).T).T

    # compute warp factor
    warp = np.dot(eq_to_out, warped_nodes - equi_nodes)
    if scaled:
        zerof = (abs(output_nodes) < 1.0-1.0e-10)
        sf = 1.0 - (zerof*output_nodes)**2
        warp = warp/sf + warp*(zerof-1)

    return warp
Beispiel #2
0
def warp_factor(n, output_nodes, scaled=True):
    """Compute warp function at order *n* and evaluate it at
    the nodes *output_nodes*.
    """

    from modepy.quadrature.jacobi_gauss import legendre_gauss_lobatto_nodes

    warped_nodes = legendre_gauss_lobatto_nodes(n)
    equi_nodes = np.linspace(-1, 1, n + 1)

    from modepy.matrices import vandermonde
    from modepy.modes import simplex_onb

    basis = simplex_onb(1, n)
    Veq = vandermonde(basis, equi_nodes)  # noqa

    # create interpolator from equi_nodes to output_nodes
    eq_to_out = la.solve(Veq.T, vandermonde(basis, output_nodes).T).T

    # compute warp factor
    warp = np.dot(eq_to_out, warped_nodes - equi_nodes)
    if scaled:
        zerof = (abs(output_nodes) < 1.0 - 1.0e-10)
        sf = 1.0 - (zerof * output_nodes)**2
        warp = warp / sf + warp * (zerof - 1)

    return warp
Beispiel #3
0
def estimate_lebesgue_constant(n, nodes, visualize=False):
    """Estimate the
    `Lebesgue constant
    <https://en.wikipedia.org/wiki/Lebesgue_constant_(interpolation)>`_
    of the *nodes* at polynomial order *n*.

    :arg nodes: an array of shape *(dims, nnodes)* as returned by
        :func:`modepy.warp_and_blend_nodes`.
    :arg visualize: visualize the function that gives rise to the
        returned Lebesgue constant. (2D only for now)
    :return: the Lebesgue constant, a scalar

    .. versionadded:: 2013.2
    """
    from modepy.matrices import vandermonde
    from modepy.modes import simplex_onb

    dims = len(nodes)
    basis = simplex_onb(dims, n)
    vdm = vandermonde(basis, nodes)

    from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \
            as gnitstam
    huge_n = 30*n
    equi_node_tuples = list(gnitstam(huge_n, dims))
    tons_of_equi_nodes = (
            np.array(equi_node_tuples, dtype=np.float64)
            / huge_n * 2 - 1).T

    eq_vdm = vandermonde(basis, tons_of_equi_nodes)
    eq_to_out = la.solve(vdm.T, eq_vdm.T).T

    lebesgue_worst = np.sum(np.abs(eq_to_out), axis=1)
    lebesgue_constant = np.max(lebesgue_worst)

    if visualize:
        print("Lebesgue constant: %g" % lebesgue_constant)
        from modepy.tools import submesh

        import mayavi.mlab as mlab
        mlab.figure(bgcolor=(1, 1, 1))
        mlab.triangular_mesh(
                tons_of_equi_nodes[0],
                tons_of_equi_nodes[1],
                lebesgue_worst / lebesgue_constant,
                submesh(equi_node_tuples))

        x, y = np.mgrid[-1:1:20j, -1:1:20j]
        mlab.mesh(x, y, 0*x, representation="wireframe", color=(0.4, 0.4, 0.4),
                line_width=0.6)

        mlab.show()

    return lebesgue_constant
Beispiel #4
0
def test_pkdo_orthogonality(dims, order, ebound):
    """Test orthogonality of simplicial bases using Grundmann-Moeller cubature."""

    from modepy.quadrature.grundmann_moeller import GrundmannMoellerSimplexQuadrature
    from modepy.modes import simplex_onb

    cub = GrundmannMoellerSimplexQuadrature(order, dims)
    basis = simplex_onb(dims, order)

    maxerr = 0
    for i, f in enumerate(basis):
        for j, g in enumerate(basis):
            if i == j:
                true_result = 1
            else:
                true_result = 0
            result = cub(lambda x: f(x)*g(x))
            err = abs(result-true_result)
            print((maxerr, err))
            maxerr = max(maxerr, err)
            if err > ebound:
                print("bad", order, i, j, err)
            assert err < ebound
Beispiel #5
0
def test_pkdo_orthogonality(dims, order, ebound):
    """Test orthogonality of simplicial bases using Grundmann-Moeller cubature."""

    from modepy.quadrature.grundmann_moeller import GrundmannMoellerSimplexQuadrature
    from modepy.modes import simplex_onb

    cub = GrundmannMoellerSimplexQuadrature(order, dims)
    basis = simplex_onb(dims, order)

    maxerr = 0
    for i, f in enumerate(basis):
        for j, g in enumerate(basis):
            if i == j:
                true_result = 1
            else:
                true_result = 0
            result = cub(lambda x: f(x) * g(x))
            err = abs(result - true_result)
            print((maxerr, err))
            maxerr = max(maxerr, err)
            if err > ebound:
                print("bad", order, i, j, err)
            assert err < ebound
Beispiel #6
0
def warp_and_refine_until_resolved(unwarped_mesh_or_refiner, warp_callable,
                                   est_rel_interp_tolerance):
    """Given an original ("unwarped") :class:`meshmode.mesh.Mesh` and a
    warping function *warp_callable* that takes and returns a mesh and a
    tolerance to which the mesh should be resolved by the mapping polynomials,
    this function will iteratively refine the *unwarped_mesh* until relative
    interpolation error estimates on the warped version are smaller than
    *est_rel_interp_tolerance* on each element.

    :returns: The refined, unwarped mesh.

    .. versionadded:: 2018.1
    """
    from modepy.modes import simplex_onb
    from modepy.matrices import vandermonde
    from modepy.modal_decay import simplex_interp_error_coefficient_estimator_matrix
    from meshmode.mesh.refinement import Refiner, RefinerWithoutAdjacency

    if isinstance(unwarped_mesh_or_refiner,
                  (Refiner, RefinerWithoutAdjacency)):
        refiner = unwarped_mesh_or_refiner
        unwarped_mesh = refiner.get_current_mesh()
    else:
        unwarped_mesh = unwarped_mesh_or_refiner
        refiner = Refiner(unwarped_mesh)

    iteration = 0

    while True:
        refine_flags = np.zeros(unwarped_mesh.nelements, dtype=bool)

        warped_mesh = warp_callable(unwarped_mesh)

        # test whether there are invalid values in warped mesh
        if not np.isfinite(warped_mesh.vertices).all():
            raise FloatingPointError(
                "Warped mesh contains non-finite vertices "
                "(NaN or Inf)")

        for group in warped_mesh.groups:
            if not np.isfinite(group.nodes).all():
                raise FloatingPointError(
                    "Warped mesh contains non-finite nodes "
                    "(NaN or Inf)")

        for egrp in warped_mesh.groups:
            dim, nunit_nodes = egrp.unit_nodes.shape

            interp_err_est_mat = simplex_interp_error_coefficient_estimator_matrix(
                egrp.unit_nodes,
                egrp.order,
                n_tail_orders=1 if warped_mesh.dim > 1 else 2)

            vdm_inv = la.inv(
                vandermonde(simplex_onb(dim, egrp.order), egrp.unit_nodes))

            mapping_coeffs = np.einsum("ij,dej->dei", vdm_inv, egrp.nodes)
            mapping_norm_2 = np.sqrt(np.sum(mapping_coeffs**2, axis=-1))

            interp_error_coeffs = np.einsum("ij,dej->dei", interp_err_est_mat,
                                            egrp.nodes)
            interp_error_norm_2 = np.sqrt(
                np.sum(interp_error_coeffs**2, axis=-1))

            # max over dimensions
            est_rel_interp_error = np.max(interp_error_norm_2 / mapping_norm_2,
                                          axis=0)

            refine_flags[
                    egrp.element_nr_base:
                    egrp.element_nr_base+egrp.nelements] = \
                            est_rel_interp_error > est_rel_interp_tolerance

        nrefined_elements = np.sum(refine_flags.astype(np.int32))
        if nrefined_elements == 0:
            break

        logger.info(
            "warp_and_refine_until_resolved: "
            "iteration %d -> splitting %d/%d elements", iteration,
            nrefined_elements, unwarped_mesh.nelements)

        unwarped_mesh = refiner.refine(refine_flags)
        iteration += 1

    return unwarped_mesh
Beispiel #7
0
tri_subtriangles = np.array(submesh(node_tuples))

# evaluate each basis function, build global tri mesh
node_count = 0
all_nodes = []
all_triangles = []
all_values = []

from modepy.modes import simplex_onb

p = 3
stretch_factor = 1.5

for (i, j), basis_func in zip(
        gnitstam(p, dims),
        simplex_onb(dims, p),
        ):

    all_nodes.append(plot_nodes + [stretch_factor*i, stretch_factor*j])
    all_triangles.append(tri_subtriangles + node_count)
    all_values.append(basis_func(eval_nodes))
    node_count += len(plot_nodes)

all_nodes = np.vstack(all_nodes)
all_triangles = np.vstack(all_triangles)
all_values = np.hstack(all_values)

# plot
import mayavi.mlab as mlab
fig = mlab.figure(bgcolor=(1, 1, 1))
mlab.triangular_mesh(
tri_subtriangles = np.array(submesh(node_tuples))

# evaluate each basis function, build global tri mesh
node_count = 0
all_nodes = []
all_triangles = []
all_values = []

from modepy.modes import simplex_onb

p = 3
stretch_factor = 1.5

for (i, j), basis_func in zip(
        gnitstam(p, dims),
        simplex_onb(dims, p),
):

    all_nodes.append(plot_nodes + [stretch_factor * i, stretch_factor * j])
    all_triangles.append(tri_subtriangles + node_count)
    all_values.append(basis_func(eval_nodes))
    node_count += len(plot_nodes)

all_nodes = np.vstack(all_nodes)
all_triangles = np.vstack(all_triangles)
all_values = np.hstack(all_values)

# plot
import mayavi.mlab as mlab
fig = mlab.figure(bgcolor=(1, 1, 1))
mlab.triangular_mesh(all_nodes[:, 0], all_nodes[:, 1], 0.2 * all_values,
Beispiel #9
0
def warp_and_refine_until_resolved(
        unwarped_mesh_or_refiner, warp_callable, est_rel_interp_tolerance):
    """Given an original ("un-warped") :class:`meshmode.mesh.Mesh` and a
    warping function *warp_callable* that takes and returns a mesh and a
    tolerance to which the mesh should be resolved by the mapping polynomials,
    this function will iteratively refine the *unwarped_mesh* until relative
    interpolation error estimates on the warped version are smaller than
    *est_rel_interp_tolerance* on each element.

    :returns: The refined, un-warped mesh.

    .. versionadded:: 2018.1
    """
    from modepy.modes import simplex_onb
    from modepy.matrices import vandermonde
    from modepy.modal_decay import simplex_interp_error_coefficient_estimator_matrix
    from meshmode.mesh.refinement import Refiner, RefinerWithoutAdjacency

    if isinstance(unwarped_mesh_or_refiner, (Refiner, RefinerWithoutAdjacency)):
        refiner = unwarped_mesh_or_refiner
        unwarped_mesh = refiner.get_current_mesh()
    else:
        unwarped_mesh = unwarped_mesh_or_refiner
        refiner = Refiner(unwarped_mesh)

    iteration = 0

    while True:
        refine_flags = np.zeros(unwarped_mesh.nelements, dtype=np.bool)

        warped_mesh = warp_callable(unwarped_mesh)

        # test whether there are invalid values in warped mesh
        if not np.isfinite(warped_mesh.vertices).all():
            raise FloatingPointError("Warped mesh contains non-finite vertices "
                                     "(NaN or Inf)")

        for group in warped_mesh.groups:
            if not np.isfinite(group.nodes).all():
                raise FloatingPointError("Warped mesh contains non-finite nodes "
                                         "(NaN or Inf)")

        for egrp in warped_mesh.groups:
            dim, nunit_nodes = egrp.unit_nodes.shape

            interp_err_est_mat = simplex_interp_error_coefficient_estimator_matrix(
                    egrp.unit_nodes, egrp.order,
                    n_tail_orders=1 if warped_mesh.dim > 1 else 2)

            vdm_inv = la.inv(
                    vandermonde(simplex_onb(dim, egrp.order), egrp.unit_nodes))

            mapping_coeffs = np.einsum("ij,dej->dei", vdm_inv, egrp.nodes)
            mapping_norm_2 = np.sqrt(np.sum(mapping_coeffs**2, axis=-1))

            interp_error_coeffs = np.einsum(
                    "ij,dej->dei", interp_err_est_mat, egrp.nodes)
            interp_error_norm_2 = np.sqrt(np.sum(interp_error_coeffs**2, axis=-1))

            # max over dimensions
            est_rel_interp_error = np.max(interp_error_norm_2/mapping_norm_2, axis=0)

            refine_flags[
                    egrp.element_nr_base:
                    egrp.element_nr_base+egrp.nelements] = \
                            est_rel_interp_error > est_rel_interp_tolerance

        nrefined_elements = np.sum(refine_flags.astype(np.int32))
        if nrefined_elements == 0:
            break

        logger.info("warp_and_refine_until_resolved: "
                "iteration %d -> splitting %d/%d elements",
                iteration, nrefined_elements, unwarped_mesh.nelements)

        unwarped_mesh = refiner.refine(refine_flags)
        iteration += 1

    return unwarped_mesh