Skip to content

Commit 48728e8

Browse files
committed
_make_cross_face_batches: refactor into multiple functions, try matching nodes exactly before going to Gauss-Newton
1 parent 21bc911 commit 48728e8

File tree

1 file changed

+83
-12
lines changed

1 file changed

+83
-12
lines changed

meshmode/discretization/connection/opposite_face.py

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import numpy as np
2525
import numpy.linalg as la
26+
from meshmode.discretization.connection.direct import InterpolationBatch
2627

2728
import logging
2829
logger = logging.getLogger(__name__)
@@ -43,15 +44,13 @@ def _make_cross_face_batches(actx,
4344
i_tgt_grp, i_src_grp,
4445
tgt_bdry_element_indices, src_bdry_element_indices):
4546

46-
from meshmode.discretization.connection.direct import InterpolationBatch
4747
if tgt_bdry_discr.dim == 0:
48-
yield InterpolationBatch(
48+
return [InterpolationBatch(
4949
from_group_index=i_src_grp,
5050
from_element_indices=freeze_from_numpy(actx, src_bdry_element_indices),
5151
to_element_indices=freeze_from_numpy(actx, tgt_bdry_element_indices),
5252
result_unit_nodes=src_bdry_discr.groups[i_src_grp].unit_nodes,
53-
to_element_face=None)
54-
return
53+
to_element_face=None)]
5554

5655
tgt_bdry_nodes = np.array([
5756
thaw_to_numpy(actx, ary[i_tgt_grp])[tgt_bdry_element_indices]
@@ -68,11 +67,74 @@ def _make_cross_face_batches(actx,
6867
src_mesh_grp = src_bdry_discr.mesh.groups[i_src_grp]
6968
src_grp = src_bdry_discr.groups[i_src_grp]
7069

70+
src_unit_nodes = _find_src_unit_nodes_by_matching(
71+
tgt_bdry_nodes=tgt_bdry_nodes,
72+
src_bdry_nodes=src_bdry_nodes,
73+
src_grp=src_grp, tol=tol)
74+
if src_unit_nodes is None:
75+
src_unit_nodes = _find_src_unit_nodes_via_gauss_newton(
76+
tgt_bdry_nodes=tgt_bdry_nodes,
77+
src_bdry_nodes=src_bdry_nodes,
78+
src_grp=src_grp, src_mesh_grp=src_mesh_grp,
79+
tgt_bdry_discr=tgt_bdry_discr, src_bdry_discr=src_bdry_discr,
80+
tol=tol)
81+
82+
return list(_find_src_unit_nodes_batches(
83+
actx=actx, src_unit_nodes=src_unit_nodes,
84+
i_src_grp=i_src_grp,
85+
tgt_bdry_element_indices=tgt_bdry_element_indices,
86+
src_bdry_element_indices=src_bdry_element_indices,
87+
tol=tol))
88+
89+
# }}}
90+
91+
92+
# {{{ _find_src_unit_nodes_by_matching
93+
94+
def _find_src_unit_nodes_by_matching(
95+
tgt_bdry_nodes,
96+
src_bdry_nodes,
97+
src_grp, tol):
98+
ambient_dim, nelements, ntgt_unit_nodes = tgt_bdry_nodes.shape
99+
100+
dist_vecs = (tgt_bdry_nodes.reshape(ambient_dim, nelements, -1, 1)
101+
- src_bdry_nodes.reshape(ambient_dim, nelements, 1, -1))
102+
103+
# shape: (nelements, num_tgt_nodes, num_source_nodes)
104+
is_close = np.sqrt(np.sum(dist_vecs**2, axis=0)) < tol
105+
106+
num_close_vertices = np.sum(is_close.astype(np.int32), axis=-1)
107+
if not (num_close_vertices == 1).all():
108+
return None
109+
110+
# Success: it's just a permutation
111+
idx = np.empty_like(is_close, dtype=np.int32)
112+
idx[:] = np.arange(src_grp.nunit_dofs).reshape(1, 1, -1)
113+
source_indices = idx[is_close].reshape(nelements, ntgt_unit_nodes)
114+
115+
# check
116+
matched_src_bdry_nodes = src_bdry_nodes[
117+
:, np.arange(nelements).reshape(-1, 1), source_indices]
118+
dist_vecs = tgt_bdry_nodes - matched_src_bdry_nodes
119+
is_close = np.sqrt(np.sum(dist_vecs**2, axis=0)) < tol
120+
assert is_close.all()
121+
122+
return src_grp.unit_nodes[:, source_indices]
123+
124+
# }}}
125+
126+
127+
# {{{ _find_src_unit_nodes_via_gauss_newton
128+
129+
def _find_src_unit_nodes_via_gauss_newton(
130+
tgt_bdry_nodes,
131+
src_bdry_nodes,
132+
src_grp, src_mesh_grp,
133+
tgt_bdry_discr, src_bdry_discr,
134+
tol):
71135
dim = src_grp.dim
72136
_, nelements, ntgt_unit_nodes = tgt_bdry_nodes.shape
73137

74-
# {{{ invert face map (using Gauss-Newton)
75-
76138
initial_guess = np.mean(src_mesh_grp.vertex_unit_coordinates(), axis=0)
77139
src_unit_nodes = np.empty((dim, nelements, ntgt_unit_nodes))
78140
src_unit_nodes[:] = initial_guess.reshape(-1, 1, 1)
@@ -162,7 +224,7 @@ def get_map_jacobian(unit_nodes):
162224

163225
# }}}
164226

165-
logger.debug("_make_cross_face_batches: begin gauss-newton")
227+
logger.debug("_find_src_unit_nodes_via_gauss_newton: begin")
166228

167229
niter = 0
168230
while True:
@@ -223,18 +285,27 @@ def get_map_jacobian(unit_nodes):
223285
max_resid = np.max(np.abs(resid))
224286

225287
if max_resid < tol:
226-
logger.debug("_make_cross_face_batches: gauss-newton: done, "
288+
logger.debug("_find_src_unit_nodes_via_gauss_newton: done, "
227289
"final residual: %g", max_resid)
228-
break
290+
return src_unit_nodes
229291

230292
niter += 1
231293
if niter > 10:
232294
raise RuntimeError("Gauss-Newton (for finding opposite-face reference "
233295
"coordinates) did not converge (residual: %g)" % max_resid)
234296

235-
# }}}
297+
raise AssertionError()
236298

237-
# {{{ find batches of src_unit_nodes
299+
# }}}
300+
301+
302+
# {{{ _find_src_unit_nodes_batches
303+
304+
def _find_src_unit_nodes_batches(
305+
actx, src_unit_nodes, i_src_grp,
306+
tgt_bdry_element_indices, src_bdry_element_indices,
307+
tol):
308+
dim, nelements, _ = src_unit_nodes.shape
238309

239310
done_elements = np.zeros(nelements, dtype=bool)
240311
while True:
@@ -261,7 +332,7 @@ def get_map_jacobian(unit_nodes):
261332
result_unit_nodes=template_unit_nodes,
262333
to_element_face=None)
263334

264-
# }}}
335+
# }}}
265336

266337

267338
def _find_ibatch_for_face(vbc_tgt_grp_batches, iface):

0 commit comments

Comments
 (0)