Skip to content

Commit 791d3c6

Browse files
committed
add test case for stretch factors
1 parent b3a050f commit 791d3c6

File tree

2 files changed

+147
-1
lines changed

2 files changed

+147
-1
lines changed

pytential/symbolic/primitives.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ def _small_mat_eigenvalues(mat):
858858
det_mat = a * d - b * c
859859

860860
# solutions to lambda**2 - tr(A) * lambda + det(A)
861-
sqrt_discriminant = cse(sqrt(tr_mat**2 - 4*det_mat))
861+
sqrt_discriminant = cse(sqrt(abs(tr_mat**2 - 4*det_mat)))
862862
return make_obj_array([
863863
(tr_mat - sqrt_discriminant) / 2,
864864
(tr_mat + sqrt_discriminant) / 2,

test/test_symbolic.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,152 @@ def test_node_reduction(actx_factory):
335335
# }}}
336336

337337

338+
# {{{ test_stretch_factor
339+
340+
def make_simplex_mesh(order):
341+
vertices = np.array([
342+
[-1, -1, 0], [1, -1, 0], [-1, 1, 0], [1, 1, 0], [3, -1, 0], [3, 1, 0],
343+
], dtype=np.float64).T
344+
vertex_indices = np.array([
345+
(0, 1, 2), (1, 3, 2),
346+
(1, 4, 3), (4, 5, 3),
347+
], dtype=np.int32)
348+
349+
from meshmode.mesh import SimplexElementGroup
350+
from meshmode.mesh.generation import make_group_from_vertices
351+
grp = make_group_from_vertices(
352+
vertices, vertex_indices, order,
353+
unit_nodes=None,
354+
group_cls=SimplexElementGroup)
355+
356+
from meshmode.mesh import Mesh
357+
return Mesh(vertices, [grp], is_conforming=True)
358+
359+
360+
def make_square_mesh(order):
361+
vertices = np.array([
362+
[-1, -1, 0], [1, -1, 0], [-1, 1, 0], [1, 1, 0],
363+
[3, -1, 0], [3, 1, 0],
364+
], dtype=np.float64).T
365+
vertex_indices = np.array([
366+
(0, 1, 2, 3), (1, 4, 3, 5)
367+
], dtype=np.int32)
368+
369+
from meshmode.mesh import TensorProductElementGroup
370+
from meshmode.mesh.generation import make_group_from_vertices
371+
grp = make_group_from_vertices(
372+
vertices, vertex_indices, order,
373+
unit_nodes=None,
374+
group_cls=TensorProductElementGroup)
375+
376+
from meshmode.mesh import Mesh
377+
return Mesh(vertices, [grp], is_conforming=True)
378+
379+
380+
def make_simplex_stretch_factors(ambient_dim):
381+
from pytential.symbolic.primitives import \
382+
_equilateral_parametrization_derivative_matrix
383+
equi_pder = _equilateral_parametrization_derivative_matrix(ambient_dim)
384+
equi_form1 = sym.cse(equi_pder.T @ equi_pder, "pd_mat_jtj")
385+
386+
from pytential.symbolic.primitives import _small_mat_eigenvalues
387+
return [
388+
sym.cse(sym.sqrt(s), f"mapping_singval_{i}")
389+
for i, s in enumerate(_small_mat_eigenvalues(4 * equi_form1))
390+
]
391+
392+
393+
def make_quad_stretch_factors(ambient_dim):
394+
pder = sym.parametrization_derivative_matrix(ambient_dim, ambient_dim - 1)
395+
form1 = sym.cse(pder.T @ pder + 1.0e-14, "pd_mat_jtj")
396+
397+
from pytential.symbolic.primitives import _small_mat_eigenvalues
398+
return [
399+
sym.cse(sym.sqrt(s), f"mapping_singval_{i}")
400+
for i, s in enumerate(_small_mat_eigenvalues(4 * form1))
401+
]
402+
403+
404+
@pytest.mark.parametrize("order", [4, 8])
405+
def test_stretch_factor(actx_factory, order, visualize=False):
406+
actx = actx_factory()
407+
408+
def wobble(x):
409+
result = np.empty_like(x)
410+
result[0] = x[0]
411+
result[1] = x[1]
412+
result[2] = np.sin(x[1]) * np.sin(x[0])
413+
414+
return result
415+
416+
from meshmode.mesh.processing import map_mesh
417+
square_mesh = map_mesh(make_square_mesh(order), wobble)
418+
simplex_mesh = map_mesh(make_simplex_mesh(order), wobble)
419+
420+
from meshmode.discretization import Discretization
421+
import meshmode.discretization.poly_element as mpoly
422+
simplex_discr = Discretization(actx, simplex_mesh,
423+
mpoly.InterpolatoryEdgeClusteredGroupFactory(order))
424+
square_discr = Discretization(actx, square_mesh,
425+
mpoly.InterpolatoryEdgeClusteredGroupFactory(order))
426+
427+
s0, s1 = bind(simplex_discr,
428+
make_simplex_stretch_factors(simplex_discr.ambient_dim))(actx)
429+
q0, q1 = bind(square_discr,
430+
make_quad_stretch_factors(square_discr.ambient_dim))(actx)
431+
432+
if not visualize:
433+
return
434+
435+
from meshmode.discretization.visualization import make_visualizer
436+
vis = make_visualizer(actx, simplex_discr, order)
437+
vis.write_vtk_file(f"stretch_factor_simplex_{order:02d}.vtu", [
438+
("s0", s0), ("s1", s1),
439+
], overwrite=True)
440+
441+
vis = make_visualizer(actx, square_discr, order)
442+
vis.write_vtk_file(f"stretch_factor_square_{order:02d}.vtu", [
443+
("s0", q0), ("s1", q1),
444+
], overwrite=True)
445+
446+
# {{{ plot simplex
447+
448+
import matplotlib.pyplot as plt
449+
fig = plt.figure(figsize=(12, 10), dpi=300)
450+
451+
xi = simplex_discr.groups[0].unit_nodes
452+
for name, sv in zip(["s0", "s1"], [s0, s1]):
453+
sv0 = actx.to_numpy(sv[0])[0].ravel()
454+
sv1 = actx.to_numpy(sv[0])[0].ravel()
455+
print(sv0, sv1)
456+
457+
ax = fig.gca()
458+
im = ax.tricontourf(xi[0], xi[1], sv0, levels=32)
459+
im = ax.tricontourf(-xi[0], -xi[1], sv1, levels=32)
460+
fig.colorbar(im, ax=ax)
461+
fig.savefig(f"stretch_factor_simplex_{order:02d}_{name}")
462+
fig.clf()
463+
464+
# }}}
465+
466+
# {{{ plot square
467+
468+
xi = square_discr.groups[0].unit_nodes
469+
for name, sv in zip(["q0", "q1"], [q0, q1]):
470+
sv = actx.to_numpy(sv[0])[0]
471+
print(sv)
472+
473+
ax = fig.gca()
474+
im = ax.tricontourf(xi[0], xi[1], sv, levels=32)
475+
fig.colorbar(im, ax=ax)
476+
fig.savefig(f"stretch_factor_square_{order:02d}_{name}")
477+
fig.clf()
478+
479+
# }}}
480+
481+
# }}}
482+
483+
338484
# You can test individual routines by typing
339485
# $ python test_symbolic.py 'test_routine()'
340486

0 commit comments

Comments
 (0)