13 for iB
in range(mesh.NumBnd()):
14 bnd2node = np.array(osPart._mesh.bnd2node[iB], copy=
False)
15 bElemInfo = mesh.bndElemInfo[iB, 0]
16 if includeIDs
is not None and bElemInfo.zone
not in includeIDs:
18 assert (bnd2node < mesh.NumNodeProc()).all(), str(bnd2node)
23 osPart.coord_mesh_to_phy(np.array(mesh.coords[n], copy=
True))
26 nodeList.append(np.array(mesh.coords[n], copy=
True))
27 nodeList = np.array(nodeList).transpose()
28 travelling_bnd_elem = pack_travelling_cell(
29 cellType=bElemInfo.getElemType(),
30 cellZone=bElemInfo.zone,
32 cell2nodeRow=[mesh.coords.trans.LGhostMapping(-1, n)
for n
in bnd2node],
36 bnd_elems.append(travelling_bnd_elem)
41 self: OversetBG2D, osPart: OversetPart2D
43 local_point_dists = {}
45 origin = np.array(self.origins[0:2])
47 for iCell
in range(mesh.NumCell()):
48 cell2node = np.array(mesh.cell2node[iCell], copy=
False)
49 assert (cell2node < mesh.NumNodeProc()).all(), str(cell2node)
50 nodeDists = osPart.dist_node[cell2node]
52 for iNode
in cell2node:
53 coords.append(np.array(mesh.coords[iNode], copy=
True))
54 coords = np.array(coords).transpose()
55 coords = osPart.coord_mesh_to_phy(coords)
56 elemInfo = mesh.cellElemInfo[iCell, 0]
57 assert elemInfo.getElemType()
in {
58 Geom.Elem.ElemType.Tri3,
59 Geom.Elem.ElemType.Quad4,
62 gridPointsCoords = origin[:,
None] + gridPoints * h
65 for iP
in range(gridPoints.shape[1]):
68 p[:2] = gridPointsCoords[:, iP]
69 distP = elem_get_interpolation_base(
70 elemInfo.getElemType(), coords, p
72 local_point_dists[tuple(gridPoints[:, iP])] = distP
73 return local_point_dists
77 """for a part to get nodal distance field
80 self (OversetPart2D): _description_
81 bc_names (list, optional): _description_. Defaults to ["WALL"].
89 self, [self._name2ID[name]
for name
in bc_names]
91 bnd_elems_local_others = MPI.allgather(bnd_elems_local)
94 for bnd_part
in bnd_elems_local_others:
95 for t, z, _, b2n, coord
in bnd_part:
96 assert t == Geom.Elem.ElemType.Line2
97 bnd_geoms.extend([coord[:, 0], coord[:, 1]])
98 tree = scipy.spatial.KDTree(np.array(bnd_geoms))
101 dists = np.ones((mesh.NumNodeProc()), dtype=np.float64) * 1e300
102 coordsFatherData = np.array(self._mesh.coords.father.data())
103 coordsFatherData = coordsFatherData.reshape((3, -1), order=
"F")
105 distq, idx = tree.query(coordsFatherData.T)
106 dists[0 : mesh.NumNode()] = distq
109 np.array(self._mesh.coords.son.data())
110 if self._mesh.coords.son.Size()
113 coordsSonData = coordsSonData.reshape((3, -1), order=
"F")
115 distq, idx = tree.query(coordsSonData.T)
116 dists[mesh.NumNode() :] = distq
117 print(f
"{mpi.rank}: maxDist: {dists.max()}")
134 part_local_dists_items = list(part_local_dists.items())
136 ijkv = np.array([v[0]
for v
in part_local_dists_items]).transpose()
138 ranks = list(self.global_ijk_to_rank(ijkv))
142 sendLists = [[]
for _
in range(mpi.size)]
144 for i, rank
in enumerate(ranks):
145 datac = part_local_dists_items[i]
146 sendLists[rank].append(datac)
148 recvLists = MPI.alltoall(sendLists)
152 ax_ranks = self.rank_to_ax_rank()
153 proc_bg_mesh_dist = np.ones(self.proc_grid_shape()) * 1e300
154 for recvL
in recvLists:
156 for g_point, v
in recvL:
158 assert g_point[ax] < self.nStarts4point[ax][ax_ranks[ax] + 1], g_point[
162 g_point[0] - self.nStarts4point[0][ax_ranks[0]],
163 g_point[1] - self.nStarts4point[1][ax_ranks[1]],
165 proc_bg_mesh_dist[l_point] = v
167 return proc_bg_mesh_dist
174 cell_bnds: OversetBG2D.cell_bnds_type,
175 dist_field: CartGridField,
177 """creates negative hole and expands it
180 self (OversetBG2D): _description_
181 part (OversetPart2D): _description_
182 bc_names (list[str]): _description_
183 cell_bnds (OversetBG2D.cell_bnds_type): _description_
184 dist_field (CartGridField): modified to have neg hole
189 dist_expanded_array = dist_field.get_expanded_array()
191 offsets = [(0, 0), (1, 0), (0, 1), (1, 1)]
192 for ijk, bnd_list
in cell_bnds.items():
193 for type, bcid, _, b2n, coords
in bnd_list:
194 assert type == Geom.Elem.ElemType.Line2
195 if bcid
in [part._name2ID[name]
for name
in bc_names]:
196 for offset
in offsets:
197 ijkp = tuple([ijk[iax] + offset[iax]
for iax
in range(2)])
198 ijkp_in_expanded = tuple(
201 - self.proc_grid_range_expanded(is_point=
True)[iax][0]
205 if dist_expanded_array[ijkp_in_expanded] > 1e299:
206 dist_expanded_array[ijkp_in_expanded] = -100
207 dist_field.set_main_data_from_expanded(dist_expanded_array)
208 dist_field.trans.startPersistentPull()
209 dist_field.trans.waitPersistentPull()
211 ijks_expanded = self.proc_grid_ijkarray(is_point=
True, expanded=
True)
212 ijks_expanded[0] -= self.proc_grid_range_expanded()[0][0]
213 ijks_expanded[1] -= self.proc_grid_range_expanded()[1][0]
214 cr = self.proc_grid_core_range_in_local_expanded(is_point=
True)
215 ijks_expanded_core = ijks_expanded[:, cr[0][0] : cr[0][1], cr[1][0] : cr[1][1]]
216 ijks_expanded_core = ijks_expanded_core.reshape((2, -1))
217 ijks_expanded_core_le = np.array([ijks_expanded_core[0] - 1, ijks_expanded_core[1]])
218 ijks_expanded_core_ri = np.array([ijks_expanded_core[0] + 1, ijks_expanded_core[1]])
219 ijks_expanded_core_lo = np.array([ijks_expanded_core[0], ijks_expanded_core[1] - 1])
220 ijks_expanded_core_up = np.array([ijks_expanded_core[0], ijks_expanded_core[1] + 1])
222 offsets = [(0, 1), (0, -1), (1, 0), (-1, 0)]
223 for iter
in range(10000):
224 dist_expanded_array = dist_field.get_expanded_array()
225 dist_expanded_array_new = np.array(dist_expanded_array)
227 for ic
in range(ijks_expanded_core.shape[1]):
228 ijk = tuple(ijks_expanded_core[:, ic])
229 if dist_expanded_array[ijk] > 1e299:
231 ijks_expanded_core_le[:, ic],
232 ijks_expanded_core_ri[:, ic],
233 ijks_expanded_core_lo[:, ic],
234 ijks_expanded_core_up[:, ic],
236 ijk_nei = tuple(ijk_nei)
238 0 <= ijk_nei[0] < dist_expanded_array.shape[0]
239 and 0 <= ijk_nei[1] < dist_expanded_array.shape[1]
240 and dist_expanded_array[ijk_nei] < 0
243 dist_expanded_array_new[ijk] = dist_expanded_array[ijk_nei]
244 count = MPI.allreduce(count, pyMPI.SUM)
246 print(f
"negative hole: iter [{iter}] Done")
249 dist_field.set_main_data_from_expanded(dist_expanded_array_new)
250 dist_field.trans.startPersistentPull()
251 dist_field.trans.waitPersistentPull()
253 print(f
"count left: {count}")
259 cell_bnds: OversetBG2D.cell_bnds_type,
260 cell_cell_inds: dict[tuple[int], set[int]],
266 elem_reqs_send = [[]
for _
in range(mpi.size)]
267 for ijk
in cell_bnds.keys():
268 assert ijk
in cell_cell_inds.keys()
269 for iCellG
in cell_cell_inds[ijk]:
270 ret, rank, val = mesh.cell2node.trans.LGlobalMapping.search(iCellG)
271 assert ret,
"search failed"
272 elem_reqs_send[rank].append((ijk, iCellG))
274 elem_reqs_recv = MPI.alltoall(elem_reqs_send)
276 elem_send = [[]
for _
in range(mpi.size)]
277 for rank_send, reqs
in enumerate(elem_reqs_recv):
278 for ijk, iCellG
in reqs:
279 ret, rank_searched, iCell = mesh.cell2node.trans.LGlobalMapping.search(
282 assert ret
and rank_searched == mpi.rank,
"search failed"
283 elem_send[rank_send].append(
284 (ijk, part.get_travelling_cell(iCell, in_phy=
True))
286 elem_recv = MPI.alltoall(elem_send)
289 cell_cells_on_bnd = defaultdict(list)
290 for ijk, travelling_cell
in itertools.chain(*elem_recv):
291 cell_cells_on_bnd[ijk].append(travelling_cell)
292 return cell_cells_on_bnd
300 send_lists = [[]
for _
in range(mpi.size)]
301 for travelling_bnd_elem
in bnd_elems:
302 type, bcid, _, b2n, coords = travelling_bnd_elem
304 self.origins[:2], self.h, coords[0:2, :]
306 ranks = self.global_ijk_to_rank(cell_ijks)
307 for ic, rank
in enumerate(ranks):
308 send_lists[rank].append((cell_ijks[:, ic], travelling_bnd_elem))
309 recv_lists = MPI.alltoall(send_lists)
311 cell_bnds = defaultdict(list)
312 for cell_ijk, travelling_bnd_elem
in itertools.chain(*recv_lists):
313 cell_ijk_t = tuple(int(v)
for v
in cell_ijk)
314 cell_bnds[cell_ijk_t].append(travelling_bnd_elem)
315 return dict(cell_bnds)
322 cell_bnds = dict(cell_bnds)
324 bg_cell_range = self.proc_grid_range(is_point=
False)
325 proc_grid_ijks_expanded = self.proc_grid_ijkarray(expanded=
True).reshape(2, -1)
327 for iIJK
in range(proc_grid_ijks_expanded.shape[1]):
328 ijk = [int(proc_grid_ijks_expanded[iax, iIJK])
for iax
in range(2)]
330 bg_cell_range[iax][0] <= ijk[iax] < bg_cell_range[iax][1]
333 if not (ijkInCore[0]
and ijkInCore[1]):
334 ijk_fringe.append(tuple(ijk))
335 ijk_fringe = np.array(ijk_fringe, dtype=np.int64).T
336 ranks = self.global_ijk_to_rank(ijk_fringe)
337 req_lists = [[]
for _
in range(mpi.size)]
338 for i, rank
in enumerate(ranks):
339 req_lists[rank].append(ijk_fringe[:, i])
340 req_cur = MPI.alltoall(req_lists)
341 send_lists_fringe_cell_bnd = [[]
for rank
in range(mpi.size)]
342 for rank_source, ijks
in enumerate(req_cur):
344 ijk_t = tuple(int(v)
for v
in ijk)
345 if ijk_t
in cell_bnds:
346 send_lists_fringe_cell_bnd[rank_source].append(
347 (ijk_t, cell_bnds[ijk_t])
349 recv_lists_fringe_cell_bnd = MPI.alltoall(send_lists_fringe_cell_bnd)
351 for ijk_t, bnds_list
in itertools.chain(*recv_lists_fringe_cell_bnd):
352 assert ijk_t
not in cell_bnds
353 cell_bnds[ijk_t] = bnds_list
363 origin = self.origins[:2]
365 send_list = [[]
for _
in range(mpi.size)]
367 for iCell
in range(mesh.NumCell()):
368 cell2node = np.array(mesh.cell2node[iCell], copy=
False)
369 assert (cell2node < mesh.NumNodeProc()).all(), str(cell2node)
371 for iNode
in cell2node:
372 coords.append(np.array(mesh.coords[iNode], copy=
True))
373 coords = np.array(coords).transpose()
374 coords = part.coord_mesh_to_phy(coords)
375 elemInfo = mesh.cellElemInfo[iCell, 0]
376 assert elemInfo.getElemType()
in {
377 Geom.Elem.ElemType.Tri3,
378 Geom.Elem.ElemType.Quad4,
391 ranks = self.global_ijk_to_rank(ijks, is_point=
False)
392 for iC
in range(ijks.shape[1]):
393 send_list[ranks[iC]].append(
394 (ijks[:, iC], mesh.cell2node.trans.LGhostMapping(-1, iCell))
397 recv_list = MPI.alltoall(send_list)
398 proc_cell_global_ijk_to_part_cell_dict = defaultdict(list)
399 d = proc_cell_global_ijk_to_part_cell_dict
400 for ijk, iCellG
in itertools.chain(*recv_list):
401 ijkt = tuple([int(v)
for v
in ijk])
402 d[ijkt].append(iCellG)
405 d[k] =
set(sorted(d[k]))
410 return proc_cell_global_ijk_to_part_cell_dict
414 self: OversetBG2D, distMap: DistMap, points: np.ndarray, rel_tol=1e-8
418 assert points.shape[0] == 2
419 points = np.reshape(points, (2, -1))
422 ranks = self.global_ijk_to_rank(ijks, is_point=
False)
425 query_send = [
set()
for _
in range(mpi.size)]
426 for iq, rank
in enumerate(ranks):
427 query_send[rank].add(tuple([int(v)
for v
in ijks[:, iq]]))
428 query_recv = MPI.alltoall(query_send)
430 data_send = [{}
for _
in range(mpi.size)]
432 proc_grid_point_dists = distMap.dist_field.get_expanded_array()
434 for rank_to, queries
in enumerate(query_recv):
438 ijk[iax] - self.proc_grid_range_expanded(is_point=
True)[iax][0]
443 proc_grid_point_dists[
444 ijk_local_p[0] + disp[0], ijk_local_p[1] + disp[1]
446 for disp
in [(0, 0), (1, 0), (0, 1), (1, 1)]
448 dists = np.array(dists)
450 if ijk
in distMap.cell_bnds:
451 bnd_elems = distMap.cell_bnds[ijk]
452 assert ijk
in distMap.cell_cells_on_bnd
453 bnd_cell_elems = distMap.cell_cells_on_bnd[ijk]
454 additional = (bnd_elems, bnd_cell_elems)
458 (ijk[0] - 1, ijk[1]),
459 (ijk[0] + 1, ijk[1]),
460 (ijk[0], ijk[1] - 1),
461 (ijk[0], ijk[1] + 1),
463 for ijk_neigh
in ijk_neighs:
465 ijk_neigh
in distMap.cell_bnds_expanded
467 additional[0].extend(distMap.cell_bnds_expanded[ijk_neigh])
469 assert ijk
not in data_send[rank_to]
470 data_send[rank_to][ijk] = (dists, additional)
472 data_recv = MPI.alltoall(data_send)
473 data_recv_merged = {k: v
for d
in data_recv
for k, v
in d.items()}
475 dist_results = np.zeros(points.shape[1]) + 1e300
476 for iq
in range(points.shape[1]):
477 ijkt = tuple([int(v)
for v
in ijks[:, iq]])
478 dists, additional = data_recv_merged[ijkt]
480 dist_results[iq] = dists.max()
482 if dists.min() > 1e299:
483 dist_results[iq] = 1e300
485 if ((0 <= dists) & (dists <= 1e299)).all():
488 self.origins[iax] + ijkt[iax] * self.h,
489 self.origins[iax] + (ijkt[iax] + 1) * self.h,
494 [(points[iax, iq] - xyz01[iax][0]) / self.h
for iax
in range(2)],
498 (0 - rel_tol <= xis) & (xis <= 1 + rel_tol)
499 ).all(), f
"{xis}, {points[:, iq]}"
503 [1 - xis[iax]
if offset[iax] == 0
else xis[iax]
for iax
in range(2)]
505 for offset
in [(0, 0), (1, 0), (0, 1), (1, 1)]
507 dist_results[iq] = np.array(bases).dot(dists)
509 assert additional
is not None, f
"{ijkt}, {iq}, {(dists.min(),dists.max())}"
510 bnd_elems, bnd_cell_elems = additional
512 for ct, _, _, _, coords
in bnd_cell_elems:
514 coords[:2, :], points[0, iq], points[1, iq]
524 for bct, _, _, _, coords
in bnd_elems:
526 edist = np.linalg.vector_norm(
527 coords[:2, :] - p[:,
None], axis=0
529 distc = min(distc, edist)
534 xi = x10.dot(x12) / x12.dot(x12)
535 if 0 <= xi
and xi <= 1:
536 distM = np.linalg.vector_norm(xi * x12 - x10)
537 distc = min(distc, distM)
539 dist_results[iq] = distc
541 if dists.max() > 1e299:
542 dist_results[iq] = dists.min()
545 dist_results[iq] = dists.min()
546 if dists.max() > 1e299:
547 dist_results[iq] = 1e300
556 self: OversetBG2D, osPart: OversetPart2D, distMap: DistMap, points: np.ndarray
561 points = np.reshape(points, (2, -1))
564 ranks = self.global_ijk_to_rank(ijks, is_point=
False)
566 query_send = [
set()
for _
in range(mpi.size)]
567 for iq, rank
in enumerate(ranks):
568 query_send[rank].add(tuple([int(v)
for v
in ijks[:, iq]]))
569 query_recv = MPI.alltoall(query_send)
571 data_send = [{}
for _
in range(mpi.size)]
572 for rank, query_recv_rank
in enumerate(query_recv):
573 for ijk
in query_recv_rank:
574 data_send[rank][ijk] = distMap.cell_cell_inds[ijk]
575 data_recv = MPI.alltoall(data_send)
576 ijk_to_cell_data_recv_merged = {k: v
for d
in data_recv
for k, v
in d.items()}
579 for v
in ijk_to_cell_data_recv_merged.values():
581 cell_req_send = [[]
for _
in range(mpi.size)]
582 for iCellG
in iCellGs:
583 ret, rank, iCell = mesh.cell2node.trans.LGlobalMapping.search(iCellG)
584 assert ret,
"search failed"
586 cell_req_send[rank].append((iCell, iCellG))
587 cell_req_recv = MPI.alltoall(cell_req_send)
588 travelling_cell_data_send = []
589 for cell_reqs
in cell_req_recv:
591 for iCell, iCellG
in cell_reqs:
592 data_c.append((iCellG, osPart.get_travelling_cell(iCell, in_phy=
True)))
593 travelling_cell_data_send.append(data_c)
594 travelling_cell_data_recv = MPI.alltoall(travelling_cell_data_send)
595 travelling_cell_data_recv_dict = {}
596 for iCellG, travelling_cell
in itertools.chain(*travelling_cell_data_recv):
597 travelling_cell_data_recv_dict[iCellG] = travelling_cell
599 template_iCellGs = []
600 for iq, rank
in enumerate(ranks):
601 ijk_t = tuple([int(v)
for v
in ijks[:, iq]])
603 (iCellG, travelling_cell_data_recv_dict[iCellG])
604 for iCellG
in ijk_to_cell_data_recv_merged[ijk_t]
607 for iCellG, travelling_cell
in cells:
608 cellType, cellZone, iCell, cell2nodeRow, coords = travelling_cell
610 Geom.Elem.ElemType.Quad4,
611 Geom.Elem.ElemType.Tri3,
614 coords[:2, :], points[0, iq], points[1, iq]
617 iCellG_template = iCellG
619 template_iCellGs.append(iCellG_template)
620 return template_iCellGs
624 self: OversetBG2D, parts: list[OversetPart2D], proc_dist_maps: list[DistMap]
629 for i
in range(len(parts)):
630 for j
in range(len(parts)):
631 check_pairs.append((i, j))
633 other_dists_nodes = [{}
for _
in range(len(parts))]
634 self_dist_nodes = [
None] * len(parts)
636 for i, j
in check_pairs:
638 dist_that = proc_dist_maps[j]
639 mesh = part_this._mesh
640 coordsFatherData = np.array(mesh.coords.father.data())
641 coordsFatherData = coordsFatherData.reshape((3, -1), order=
"F")
644 np.array(mesh.coords.son.data())
645 if mesh.coords.son.Size()
648 coordsSonData = coordsSonData.reshape((3, -1), order=
"F")
650 coordsFullData = np.concat([coordsFatherData, coordsSonData], axis=1)
651 coordsFullData = part_this.coord_mesh_to_phy(
654 coordsFullData = coordsFullData[:2, :]
657 self_dist_nodes[i] = self.query_dist_from_points(dist_that, coordsFullData)
659 other_dists_nodes[i][j] = self.query_dist_from_points(
660 dist_that, coordsFullData
663 min_dists_nodes_other = []
664 for i, other_set
in enumerate(other_dists_nodes):
666 mesh = part_this._mesh
667 min_dist_other = np.zeros((mesh.NumNodeProc())) + 1e301
668 for other_dist
in other_set.values():
669 min_dist_other = np.minimum(min_dist_other, other_dist)
671 min_dists_nodes_other.append(min_dist_other)
675 for i, part
in enumerate(parts):
677 self_dist_nodes[i] * 0.9
678 > min_dists_nodes_other[i]
685 cell_type = np.zeros((mesh.NumCell()))
686 for iCell
in range(mesh.NumCell()):
687 c2n = mesh.cell2node[iCell].tolist()
688 c2n_is_hole = node_is_hole[c2n]
689 cell_type[iCell] = 1
if c2n_is_hole.all()
else 0
693 cell_type_arr.TransAttach()
694 cell_type_arr.father.Resize(mesh.NumCell())
695 cell_type_arr_father_data_in = np.array(cell_type_arr.father.data(), copy=
False)
696 cell_type_arr_father_data_in[:] = cell_type.flat
697 cell_type_arr.trans.BorrowGGIndexing(mesh.cell2node.trans)
698 cell_type_arr.trans.createMPITypes()
699 cell_type_arr.trans.pullOnce()
700 cell_type_arrs.append(cell_type_arr)
701 return (cell_type_arrs, other_dists_nodes)
706 parts: list[OversetPart2D],
707 proc_dist_maps: list[DistMap],
712 points = np.reshape(points, (2, -1))
714 assert len(parts) == len(proc_dist_maps)
717 for dist_that
in proc_dist_maps:
718 dists_pts.append(self.query_dist_from_points(dist_that, points))
720 dist_pts_a = np.array(dists_pts, dtype=np.float64)
721 min_dist_loc = np.argmin(dist_pts_a, axis=0)
722 min_dist = np.min(dist_pts_a, axis=0)
723 inds = np.arange(len(min_dist))
724 iCellGs = np.ones_like(inds) * -1
726 for i, part
in enumerate(parts):
727 inds_c = inds[min_dist_loc == i]
728 points_c = points[:, inds_c]
729 iCellGs[inds_c] = self.query_template_cell_from_points(
730 part, proc_dist_maps[i], points_c
733 return (np.array(min_dist_loc), np.array(iCellGs))