def warp_and_blend_nodes_2d(n, node_tuples=None): try: alpha = _alpha_opt_2d[n-1] except IndexError: alpha = 5/3 if node_tuples is None: from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 2)) else: if len(node_tuples) != (n+1)*(n+2)//2: raise ValueError("node_tuples list does not have the correct length") # shape: (2, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64)/n*2 - 1).T from modepy.tools import ( unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit) bary = unit_to_barycentric(unit_nodes) return equilateral_to_unit( barycentric_to_equilateral(bary) + _2d_equilateral_shift(n, bary, alpha))
def test_barycentric_coordinate_map(dims): from random import Random rng = Random(17) n = 5 unit = np.empty((dims, n)) from modepy.tools import ( pick_random_simplex_unit_coordinate, unit_to_barycentric, barycentric_to_unit, barycentric_to_equilateral, equilateral_to_unit,) for i in range(n): unit[:, i] = pick_random_simplex_unit_coordinate(rng, dims) bary = unit_to_barycentric(unit) assert (np.abs(np.sum(bary, axis=0) - 1) < 1e-15).all() assert (bary >= 0).all() unit2 = barycentric_to_unit(bary) assert la.norm(unit-unit2) < 1e-14 equi = barycentric_to_equilateral(bary) unit3 = equilateral_to_unit(equi) assert la.norm(unit-unit3) < 1e-14
def test_barycentric_coordinate_map(dims): from random import Random rng = Random(17) n = 5 unit = np.empty((dims, n)) from modepy.tools import ( pick_random_simplex_unit_coordinate, unit_to_barycentric, barycentric_to_unit, barycentric_to_equilateral, equilateral_to_unit, ) for i in range(n): unit[:, i] = pick_random_simplex_unit_coordinate(rng, dims) bary = unit_to_barycentric(unit) assert (np.abs(np.sum(bary, axis=0) - 1) < 1e-15).all() assert (bary >= 0).all() unit2 = barycentric_to_unit(bary) assert la.norm(unit - unit2) < 1e-14 equi = barycentric_to_equilateral(bary) unit3 = equilateral_to_unit(equi) assert la.norm(unit - unit3) < 1e-14
def test_barycentric_coordinate_map(dims): n = 100 from modepy.tools import ( unit_to_barycentric, barycentric_to_unit, barycentric_to_equilateral, equilateral_to_unit, ) rng = np.random.Generator(np.random.PCG64(17)) unit = nd.random_nodes_for_shape(shp.Simplex(dims), n, rng=rng) bary = unit_to_barycentric(unit) assert (np.abs(np.sum(bary, axis=0) - 1) < 1e-15).all() assert (bary >= 0).all() unit2 = barycentric_to_unit(bary) assert la.norm(unit - unit2) < 1e-14 equi = barycentric_to_equilateral(bary) unit3 = equilateral_to_unit(equi) assert la.norm(unit - unit3) < 1e-14
def warp_and_blend_nodes_2d(n, node_tuples=None): try: alpha = _alpha_opt_2d[n - 1] except IndexError: alpha = 5 / 3 space = PN(2, n) if node_tuples is None: node_tuples = node_tuples_for_space(space) else: if len(node_tuples) != space.space_dim: raise ValueError( "'node_tuples' list does not have the correct length") # shape: (2, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64) / n * 2 - 1).T from modepy.tools import (unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit) bary = unit_to_barycentric(unit_nodes) return equilateral_to_unit( barycentric_to_equilateral(bary) + _2d_equilateral_shift(n, bary, alpha))
def warp_and_blend_nodes_3d(n, node_tuples=None): try: alpha = _alpha_opt_3d[n-1] except IndexError: alpha = 1. if node_tuples is None: from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 3)) else: if len(node_tuples) != (n+1)*(n+2)*(n+3)//6: raise ValueError("node_tuples list does not have the correct length") # shape: (3, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64)/n*2 - 1).T from modepy.tools import ( unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit, EQUILATERAL_VERTICES) bary = unit_to_barycentric(unit_nodes) equi = barycentric_to_equilateral(bary) equi_vertices = EQUILATERAL_VERTICES[3] # total number of nodes and tolerance tol = 1e-8 shift = np.zeros_like(equi) for i1, i2, i3, i4, vertex_step in [ (0, 1, 2, 3, -1), (1, 2, 3, 0, -1), (2, 3, 0, 1, -1), (3, 0, 1, 2, -1), ]: vi2, vi3, vi4 = [(i1 + vertex_step*i) % 4 for i in range(1, 4)] # all vertices have the same distance from the origin tangent1 = equi_vertices[vi3] - equi_vertices[vi4] tangent1 /= la.norm(tangent1) tangent2 = equi_vertices[vi2] - equi_vertices[vi3] tangent2 -= np.dot(tangent1, tangent2)*tangent1 tangent2 /= la.norm(tangent2) sub_bary = bary[[i2, i3, i4]] warp1, warp2 = _2d_equilateral_shift(n, sub_bary, alpha) l1 = bary[i1] l2, l3, l4 = sub_bary blend = l2*l3*l4 denom = (l2+0.5*l1)*(l3+0.5*l1)*(l4+0.5*l1) denom_ok = denom > tol blend[denom_ok] = ( (1+(alpha*l1[denom_ok])**2) * blend[denom_ok] / denom[denom_ok]) shift = shift + (blend*warp1)[np.newaxis, :] * tangent1[:, np.newaxis] shift = shift + (blend*warp2)[np.newaxis, :] * tangent2[:, np.newaxis] is_face = (l1 < tol) & ((l2 > tol) | (l3 > tol) | (l4 > tol)) # assign face warp separately shift[:, is_face] = ( + warp1[is_face][np.newaxis, :] * tangent1[:, np.newaxis] + warp2[is_face][np.newaxis, :] * tangent2[:, np.newaxis] ) return equilateral_to_unit(equi + shift)
def warp_and_blend_nodes_3d(n, node_tuples=None): try: alpha = _alpha_opt_3d[n - 1] except IndexError: alpha = 1. if node_tuples is None: from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 3)) else: if len(node_tuples) != (n + 1) * (n + 2) * (n + 3) // 6: raise ValueError( "node_tuples list does not have the correct length") # shape: (3, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64) / n * 2 - 1).T from modepy.tools import (unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit, EQUILATERAL_VERTICES) bary = unit_to_barycentric(unit_nodes) equi = barycentric_to_equilateral(bary) equi_vertices = EQUILATERAL_VERTICES[3] # total number of nodes and tolerance tol = 1e-8 shift = np.zeros_like(equi) for i1, i2, i3, i4, vertex_step in [ (0, 1, 2, 3, -1), (1, 2, 3, 0, -1), (2, 3, 0, 1, -1), (3, 0, 1, 2, -1), ]: vi2, vi3, vi4 = [(i1 + vertex_step * i) % 4 for i in range(1, 4)] # all vertices have the same distance from the origin tangent1 = equi_vertices[vi3] - equi_vertices[vi4] tangent1 /= la.norm(tangent1) tangent2 = equi_vertices[vi2] - equi_vertices[vi3] tangent2 -= np.dot(tangent1, tangent2) * tangent1 tangent2 /= la.norm(tangent2) sub_bary = bary[[i2, i3, i4]] warp1, warp2 = _2d_equilateral_shift(n, sub_bary, alpha) l1 = bary[i1] l2, l3, l4 = sub_bary blend = l2 * l3 * l4 denom = (l2 + 0.5 * l1) * (l3 + 0.5 * l1) * (l4 + 0.5 * l1) denom_ok = denom > tol blend[denom_ok] = ((1 + (alpha * l1[denom_ok])**2) * blend[denom_ok] / denom[denom_ok]) shift = shift + (blend * warp1)[np.newaxis, :] * tangent1[:, np.newaxis] shift = shift + (blend * warp2)[np.newaxis, :] * tangent2[:, np.newaxis] is_face = (l1 < tol) & ((l2 > tol) | (l3 > tol) | (l4 > tol)) # assign face warp separately shift[:, is_face] = ( +warp1[is_face][np.newaxis, :] * tangent1[:, np.newaxis] + warp2[is_face][np.newaxis, :] * tangent2[:, np.newaxis]) return equilateral_to_unit(equi + shift)