@@ -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