Skip to content

Commit 0d5adb2

Browse files
committed
tests
1 parent 339b3e9 commit 0d5adb2

File tree

1 file changed

+95
-33
lines changed

1 file changed

+95
-33
lines changed

tests/firedrake/submesh/test_submesh_solve.py

Lines changed: 95 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -463,12 +463,12 @@ def test_submesh_solve_cell_cell_equation_bc(nref, degree, simplex):
463463
assert sqrt(assemble(inner(sol[1] - x * y, sol[1] - x * y) * dx_inner)) < 1.e-12
464464

465465

466-
def _test_submesh_solve_quad_triangle_convergence(nref, degree):
466+
def _test_submesh_solve_quad_triangle_poisson(nref, degree):
467467
dim = 2
468468
label_ext = 1
469469
label_interf = 2
470470
distribution_parameters_noop = {
471-
"partition": False,
471+
"partition": True,
472472
"overlap_type": (DistributedMeshOverlapType.NONE, 0),
473473
}
474474
mesh = Mesh(os.path.join(cwd, "..", "meshes", "mixed_cell_unit_square.msh"), distribution_parameters=distribution_parameters_noop)
@@ -523,20 +523,20 @@ def _test_submesh_solve_quad_triangle_convergence(nref, degree):
523523
bc_q = DirichletBC(V.sub(1), g_q, label_ext)
524524
solve(a == L, sol, bcs=[bc_q])
525525
sol_t, sol_q = split(sol)
526-
L2error_t = assemble(inner(sol_t - g_t, sol_t - g_t) * dx_t)
527-
L2error_q = assemble(inner(sol_q - g_q, sol_q - g_q) * dx_q)
528-
H1error_t = assemble((inner(sol_t - g_t, sol_t - g_t) + inner(grad(sol_t - g_t), grad(sol_t - g_t)))* dx_t)
529-
H1error_q = assemble((inner(sol_q - g_q, sol_q - g_q) + inner(grad(sol_q - g_q), grad(sol_q - g_q)))* dx_q)
530-
return sqrt(L2error_t + L2error_q), sqrt(H1error_t + H1error_q)
526+
L2Error_t = assemble(inner(sol_t - g_t, sol_t - g_t) * dx_t)
527+
L2Error_q = assemble(inner(sol_q - g_q, sol_q - g_q) * dx_q)
528+
H1Error_t = L2Error_t + assemble(inner(grad(sol_t - g_t), grad(sol_t - g_t))* dx_t)
529+
H1Error_q = L2Error_q + assemble(inner(grad(sol_q - g_q), grad(sol_q - g_q))* dx_q)
530+
return sqrt(L2Error_t + L2Error_q), sqrt(H1Error_t + H1Error_q)
531531

532532

533533
@pytest.mark.parallel(nprocs=8)
534-
def test_submesh_solve_quad_triangle_convergence():
534+
def test_submesh_solve_quad_triangle_poisson_convergence():
535535
for degree in range(1, 5):
536536
L2Errors = []
537537
H1Errors = []
538538
for nref in range(4):
539-
L2Error, H1Error = _test_submesh_solve_quad_triangle_convergence(nref, degree)
539+
L2Error, H1Error = _test_submesh_solve_quad_triangle_poisson(nref, degree)
540540
L2Errors.append(L2Error)
541541
H1Errors.append(H1Error)
542542
L2Errors = [np.log2(c) - np.log2(f) for c, f in zip(L2Errors[:-1], L2Errors[1:])]
@@ -545,25 +545,26 @@ def test_submesh_solve_quad_triangle_convergence():
545545
assert (np.array(H1Errors) > (degree) * 0.995).all()
546546

547547

548-
@pytest.mark.parallel(nprocs=8)
549-
@pytest.mark.parametrize('simplex', [True, False])
550-
@pytest.mark.parametrize('direction', [0, 1, 2])
551-
def test_submesh_solve_hex_quad_convergence(simplex, direction):
548+
def _test_submesh_solve_3d_2d_poisson(simplex, direction, nref, degree):
552549
dim = 3
550+
distribution_parameters_noop = {
551+
"partition": True,
552+
"overlap_type": (DistributedMeshOverlapType.NONE, 0),
553+
}
553554
distribution_parameters={
554555
"overlap_type": (DistributedMeshOverlapType.RIDGE, 1),
555556
}
556557
if simplex:
557-
nref = 3
558-
mesh = BoxMesh(2 ** nref, 2 ** nref, 2 ** nref, 1., 1., 1., hexahedral=False, distribution_parameters=distribution_parameters)
558+
nref_simplex = 3
559+
mesh = BoxMesh(2 ** nref_simplex, 2 ** nref_simplex, 2 ** nref_simplex, 1., 1., 1., hexahedral=False, distribution_parameters=distribution_parameters_noop)
559560
xyz = SpatialCoordinate(mesh)
560561
DG0 = FunctionSpace(mesh, "DG", 0)
561562
c1 = Function(DG0).interpolate(conditional(xyz[direction] < 0.318310, 1, 0))
562563
c2 = Function(DG0).interpolate(conditional(xyz[direction] > 0.318310, 1, 0))
563564
mesh = RelabeledMesh(mesh, [c1, c2], [1, 2])
564565
family = "P"
565566
else:
566-
mesh = Mesh(join(cwd, "..", "meshes", "cube_hex.msh"), distribution_parameters=distribution_parameters)
567+
mesh = Mesh(join(cwd, "..", "meshes", "cube_hex.msh"), distribution_parameters=distribution_parameters_noop)
567568
xyz = SpatialCoordinate(mesh)
568569
DG0 = FunctionSpace(mesh, "DQ", 0)
569570
c1 = Function(DG0).interpolate(conditional(xyz[direction] < 0.318310, 1, 0))
@@ -577,6 +578,13 @@ def test_submesh_solve_hex_quad_convergence(simplex, direction):
577578
f6 = Function(HDivTrace0).interpolate(conditional(xyz[2] < .999, 1, 0))
578579
mesh = RelabeledMesh(mesh, [c1, c2, f1, f2, f3, f4, f5, f6], [1, 2, 1, 2, 3, 4, 5, 6])
579580
family = "Q"
581+
plex = mesh.topology_dm
582+
for _ in range(nref):
583+
plex = plex.refine()
584+
plex.removeLabel("pyop2_core")
585+
plex.removeLabel("pyop2_owned")
586+
plex.removeLabel("pyop2_ghost")
587+
mesh = Mesh(plex, distribution_parameters=distribution_parameters)
580588
mesh1 = Submesh(mesh, dim, 1)
581589
x1, y1, z1 = SpatialCoordinate(mesh1)
582590
mesh2 = Submesh(mesh, dim, 2)
@@ -586,17 +594,23 @@ def test_submesh_solve_hex_quad_convergence(simplex, direction):
586594
dx1 = Measure("dx", mesh1)
587595
dx2 = Measure("dx", mesh2)
588596
dx12 = Measure("dx", mesh12)
589-
dx12_ds1 = Measure("dx", mesh12, intersect_measures=(Measure("ds", mesh1),))
590-
ds1_dx12 = Measure("ds", mesh1, intersect_measures=(Measure("dx", mesh12),))
597+
ds1_ds2 = Measure("ds", mesh1, intersect_measures=(Measure("ds", mesh2),))
591598
ds2_dx12 = Measure("ds", mesh2, intersect_measures=(Measure("dx", mesh12),))
599+
dx12_ds1_ds2 = Measure(
600+
"dx", mesh12,
601+
intersect_measures=(
602+
Measure("ds", mesh1),
603+
Measure("ds", mesh2),
604+
)
605+
)
592606
# Check sanity.
593607
vol1 = assemble(Constant(1) * dx1)
594608
vol2 = assemble(Constant(1) * dx2)
595-
assert abs(vol1 + vol2 - 1.) < 1.e-14
609+
assert abs(vol1 + vol2 - 1.) < 1.e-13
596610
# Solve Poisson problem.
597-
V1 = FunctionSpace(mesh1, family, 3)
598-
V12 = FunctionSpace(mesh12, family, 5)
599-
V2 = FunctionSpace(mesh2, family, 4)
611+
V1 = FunctionSpace(mesh1, family, degree)
612+
V12 = FunctionSpace(mesh12, family, degree)
613+
V2 = FunctionSpace(mesh2, family, degree)
600614
V = V1 * V12 * V2
601615
u = TrialFunction(V)
602616
v = TestFunction(V)
@@ -607,22 +621,70 @@ def test_submesh_solve_hex_quad_convergence(simplex, direction):
607621
f1 = 12 * pi**2 * g1
608622
f2 = 12 * pi**2 * g2
609623
n1 = FacetNormal(mesh1)
624+
n2 = FacetNormal(mesh2)
625+
h = 0.1 / 2**nref # roughly
610626
a = (
611-
inner(grad(u1), grad(v1)) * dx1 - inner(u12, v1) * ds1_dx12(label_interf) +
612-
inner(u12, v12) * dx12 +
613-
inner(grad(u2), grad(v2)) * dx2 + inner(u12, v2) * ds2_dx12(label_interf)
627+
inner(grad(u1), grad(v1)) * dx1 +
628+
inner(grad(u2), grad(v2)) * dx2
629+
- inner(
630+
u12,
631+
(v1 - v2)
632+
) * dx12_ds1_ds2
633+
- inner(
634+
(u1 * n1 + u2 * n2),
635+
(grad(v1) + grad(v2)) / 2
636+
) * dx12_ds1_ds2
637+
+ 100 / h * inner(u1 - u2, v1 - v2) * ds1_ds2(label_interf) # Can also use dx12_ds1_ds2.
638+
+ inner(
639+
(dot(grad(u1), n1) - dot(grad(u2), n1)) / 2 - u12,
640+
v12
641+
) * dx12_ds1_ds2
614642
)
615643
L = (
616644
inner(f1, v1) * dx1 +
617-
inner(dot(grad(g1), n1), v12) * dx12_ds1 +
618645
inner(f2, v2) * dx2
619646
)
620647
sol = Function(V)
621-
bc1 = DirichletBC(V.sub(0), g1, (2 * direction + 1,))
622-
bc2 = DirichletBC(V.sub(2), g2, (2 * direction + 2,))
623-
solve(a == L, sol, bcs=[bc1, bc2])
648+
bc1 = DirichletBC(V.sub(0), g1, [i for i in range(1, 7) if i != 2 * direction + 2])
649+
bc2 = DirichletBC(V.sub(2), g2, [i for i in range(1, 7) if i != 2 * direction + 1])
650+
solver_parameters = {
651+
"mat_type": "matfree",
652+
"ksp_type": "gmres",
653+
"ksp_rtol": 1.e-14,
654+
"pc_type": "jacobi",
655+
}
656+
solve(a == L, sol, bcs=[bc1, bc2], solver_parameters=solver_parameters)
624657
sol1, sol12, sol2 = split(sol)
625-
error1 = assemble(inner(sol1 - g1, sol1 - g1) * dx1)
626-
error2 = assemble(inner(sol2 - g2, sol2 - g2) * dx2)
627-
assert sqrt(error1) < 4.e-4
628-
assert sqrt(error2) < 4.e-5
658+
L2Error1 = assemble(inner(sol1 - g1, sol1 - g1) * dx1)
659+
L2Error2 = assemble(inner(sol2 - g2, sol2 - g2) * dx2)
660+
H1Error1 = L2Error1 + assemble(inner(grad(sol1 - g1), grad(sol1 - g1))* dx1)
661+
H1Error2 = L2Error2 + assemble(inner(grad(sol2 - g2), grad(sol2 - g2))* dx2)
662+
return sqrt(L2Error1 + L2Error2), sqrt(H1Error2 + H1Error2)
663+
664+
665+
@pytest.mark.parallel(nprocs=6)
666+
@pytest.mark.parametrize('simplex', [True, False])
667+
@pytest.mark.parametrize('direction', [0, 1, 2])
668+
def test_submesh_solve_3d_2d_poisson_sanity(simplex, direction):
669+
nref = 0
670+
degree = 4
671+
L2Error, H1Error = _test_submesh_solve_3d_2d_poisson(simplex, direction, nref, degree)
672+
assert L2Error < 2.e-4
673+
assert H1Error < 3.e-2
674+
675+
676+
@pytest.mark.parallel(nprocs=8)
677+
@pytest.mark.parametrize('simplex', [False])
678+
@pytest.mark.parametrize('direction', [0])
679+
@pytest.mark.parametrize('degree', [3])
680+
def test_submesh_solve_3d_2d_poisson_convergence(simplex, direction, degree):
681+
L2Errors = []
682+
H1Errors = []
683+
for nref in range(2):
684+
L2Error, H1Error = _test_submesh_solve_3d_2d_poisson(simplex, direction, nref, degree)
685+
L2Errors.append(L2Error)
686+
H1Errors.append(H1Error)
687+
L2Errors = [np.log2(c) - np.log2(f) for c, f in zip(L2Errors[:-1], L2Errors[1:])]
688+
H1Errors = [np.log2(c) - np.log2(f) for c, f in zip(H1Errors[:-1], H1Errors[1:])]
689+
assert (np.array(L2Errors) > (degree + 1) * 0.98).all()
690+
assert (np.array(H1Errors) > (degree) * 0.98).all()

0 commit comments

Comments
 (0)