@@ -1254,21 +1254,34 @@ def generate_box_mesh(
12541254
12551255 shape_m1 = tuple (max (si - 1 , 0 ) for si in shape )
12561256
1257+ box_faces = [
1258+ side + str (axis )
1259+ for axis in range (dim )
1260+ for side in ["-" , "+" ]]
1261+
12571262 if dim == 1 :
12581263 if mesh_type is not None :
12591264 raise ValueError (f"unsupported mesh type: '{ mesh_type } '" )
12601265
12611266 nelements = shape_m1 [0 ]
12621267 nvertices_per_element = 2
1263- el_vertices = np .empty ((nelements , nvertices_per_element ), dtype = np .int32 )
12641268
1265- for i in range (shape_m1 [0 ]):
1266- # a--b
1269+ if nelements > 0 :
1270+ base_i = np .arange (shape_m1 [0 ])
1271+
1272+ a0 = vertex_indices [base_i ]
1273+ a1 = vertex_indices [base_i + 1 ]
12671274
1268- a = vertex_indices [i ]
1269- b = vertex_indices [i + 1 ]
1275+ el_vertices = np .array ([a0 , a1 ], dtype = np .int32 ).T
1276+ box_face_to_elements = {
1277+ "-0" : np .array ([0 ], dtype = np .int32 ),
1278+ "+0" : np .array ([shape_m1 [0 ]- 1 ], dtype = np .int32 )}
12701279
1271- el_vertices [i , :] = (a , b )
1280+ else :
1281+ el_vertices = np .empty ((0 , nvertices_per_element ), dtype = np .int32 )
1282+ box_face_to_elements = {
1283+ box_face : np .array ([], dtype = np .int32 )
1284+ for box_face in box_faces }
12721285
12731286 elif dim == 2 :
12741287 if is_tp :
@@ -1306,38 +1319,87 @@ def generate_box_mesh(
13061319 raise ValueError (f"unsupported mesh type: '{ mesh_type } '" )
13071320
13081321 nelements = nsubelements * product (shape_m1 )
1309- el_vertices = np .empty ((nelements , nvertices_per_element ), dtype = np .int32 )
1310-
1311- iel = 0
1312- for i in range (shape_m1 [0 ]):
1313- for j in range (shape_m1 [1 ]):
13141322
1315- # c--d
1316- # | |
1317- # a--b
1323+ if nelements > 0 :
1324+ base_idx_tuples = np .array (list (np .ndindex (shape_m1 )))
13181325
1319- a = vertex_indices [i , j ]
1320- b = vertex_indices [i + 1 , j ]
1321- c = vertex_indices [i , j + 1 ]
1322- d = vertex_indices [i + 1 , j + 1 ]
1326+ base_i = base_idx_tuples [:, 0 ]
1327+ base_j = base_idx_tuples [:, 1 ]
13231328
1324- if is_tp :
1325- el_vertices [iel , :] = (a , b , c , d )
1329+ a00 = vertex_indices [base_i , base_j ]
1330+ a01 = vertex_indices [base_i , base_j + 1 ]
1331+ a10 = vertex_indices [base_i + 1 , base_j ]
1332+ a11 = vertex_indices [base_i + 1 , base_j + 1 ]
13261333
1327- elif mesh_type == "X" :
1328- m = midpoint_indices [i , j ]
1329- el_vertices [iel :iel + 4 , :] = [
1330- (a , b , m ),
1331- (b , d , m ),
1332- (d , c , m ),
1333- (c , a , m )]
1334+ if is_tp :
1335+ el_vertices = np .array ([a00 , a10 , a01 , a11 ], dtype = np .int32 ).T
13341336
1335- else :
1336- el_vertices [iel :iel + 2 , :] = [
1337- (a , b , c ),
1338- (d , c , b )]
1339-
1340- iel += nsubelements
1337+ box_face_to_elements = {}
1338+ for box_face in box_faces :
1339+ side , axis = box_face
1340+ axis = int (axis )
1341+ if side == "-" :
1342+ elements , = np .where (base_idx_tuples [:, axis ] == 0 )
1343+ else :
1344+ elements , = np .where (
1345+ base_idx_tuples [:, axis ] == shape_m1 [axis ]- 1 )
1346+ box_face_to_elements [box_face ] = elements
1347+
1348+ elif mesh_type == "X" :
1349+ m = midpoint_indices [base_i , base_j ]
1350+ el_vertices = np .empty (
1351+ (nelements , nvertices_per_element ), dtype = np .int32 )
1352+ el_vertices [0 ::4 , :] = np .array ([a00 , a10 , m ]).T
1353+ el_vertices [1 ::4 , :] = np .array ([a10 , a11 , m ]).T
1354+ el_vertices [2 ::4 , :] = np .array ([a11 , a01 , m ]).T
1355+ el_vertices [3 ::4 , :] = np .array ([a01 , a00 , m ]).T
1356+
1357+ box_face_to_elements = {}
1358+ for box_face in box_faces :
1359+ side , axis = box_face
1360+ axis = int (axis )
1361+ if side == "-" :
1362+ box_elements , = np .where (base_idx_tuples [:, axis ] == 0 )
1363+ else :
1364+ box_elements , = np .where (
1365+ base_idx_tuples [:, axis ] == shape_m1 [axis ]- 1 )
1366+ if box_face == "-0" :
1367+ subelement_offset = 3
1368+ if box_face == "+0" :
1369+ subelement_offset = 1
1370+ if box_face == "-1" :
1371+ subelement_offset = 0
1372+ if box_face == "+1" :
1373+ subelement_offset = 2
1374+ box_face_to_elements [box_face ] = \
1375+ 4 * box_elements + subelement_offset
1376+
1377+ else :
1378+ el_vertices = np .empty (
1379+ (nelements , nvertices_per_element ), dtype = np .int32 )
1380+ el_vertices [0 ::2 , :] = np .array ([a00 , a10 , a01 ]).T
1381+ el_vertices [1 ::2 , :] = np .array ([a11 , a01 , a10 ]).T
1382+
1383+ box_face_to_elements = {}
1384+ for box_face in box_faces :
1385+ side , axis = box_face
1386+ axis = int (axis )
1387+ if side == "-" :
1388+ box_elements , = np .where (base_idx_tuples [:, axis ] == 0 )
1389+ else :
1390+ box_elements , = np .where (
1391+ base_idx_tuples [:, axis ] == shape_m1 [axis ]- 1 )
1392+ if side == "-" :
1393+ subelement_offset = 0
1394+ if side == "+" :
1395+ subelement_offset = 1
1396+ box_face_to_elements [box_face ] = \
1397+ 2 * box_elements + subelement_offset
1398+ else :
1399+ el_vertices = np .empty ((0 , nvertices_per_element ), dtype = np .int32 )
1400+ box_face_to_elements = {
1401+ box_face : np .array ([], dtype = np .int32 )
1402+ for box_face in box_faces }
13411403
13421404 elif dim == 3 :
13431405 if is_tp :
@@ -1355,38 +1417,78 @@ def generate_box_mesh(
13551417 raise ValueError (f"unsupported mesh type: '{ mesh_type } '" )
13561418
13571419 nelements = nsubelements * product (shape_m1 )
1358- el_vertices = np .empty ((nelements , nvertices_per_element ), dtype = np .int32 )
1359-
1360- iel = 0
1361- for i in range (shape_m1 [0 ]):
1362- for j in range (shape_m1 [1 ]):
1363- for k in range (shape_m1 [2 ]):
1364-
1365- a000 = vertex_indices [i , j , k ]
1366- a001 = vertex_indices [i , j , k + 1 ]
1367- a010 = vertex_indices [i , j + 1 , k ]
1368- a011 = vertex_indices [i , j + 1 , k + 1 ]
1369-
1370- a100 = vertex_indices [i + 1 , j , k ]
1371- a101 = vertex_indices [i + 1 , j , k + 1 ]
1372- a110 = vertex_indices [i + 1 , j + 1 , k ]
1373- a111 = vertex_indices [i + 1 , j + 1 , k + 1 ]
1374-
1375- if is_tp :
1376- el_vertices [iel , :] = (
1377- a000 , a100 , a010 , a110 ,
1378- a001 , a101 , a011 , a111 )
13791420
1421+ if nelements > 0 :
1422+ base_idx_tuples = np .array (list (np .ndindex (shape_m1 )))
1423+
1424+ base_i = base_idx_tuples [:, 0 ]
1425+ base_j = base_idx_tuples [:, 1 ]
1426+ base_k = base_idx_tuples [:, 2 ]
1427+
1428+ a000 = vertex_indices [base_i , base_j , base_k ]
1429+ a001 = vertex_indices [base_i , base_j , base_k + 1 ]
1430+ a010 = vertex_indices [base_i , base_j + 1 , base_k ]
1431+ a011 = vertex_indices [base_i , base_j + 1 , base_k + 1 ]
1432+ a100 = vertex_indices [base_i + 1 , base_j , base_k ]
1433+ a101 = vertex_indices [base_i + 1 , base_j , base_k + 1 ]
1434+ a110 = vertex_indices [base_i + 1 , base_j + 1 , base_k ]
1435+ a111 = vertex_indices [base_i + 1 , base_j + 1 , base_k + 1 ]
1436+
1437+ if is_tp :
1438+ el_vertices = np .array ([
1439+ a000 , a100 , a010 , a110 ,
1440+ a001 , a101 , a011 , a111 ], dtype = np .int32 ).T
1441+
1442+ box_face_to_elements = {}
1443+ for box_face in box_faces :
1444+ side , axis = box_face
1445+ axis = int (axis )
1446+ if side == "-" :
1447+ elements , = np .where (base_idx_tuples [:, axis ] == 0 )
13801448 else :
1381- el_vertices [iel :iel + 6 , :] = [
1382- (a000 , a100 , a010 , a001 ),
1383- (a101 , a100 , a001 , a010 ),
1384- (a101 , a011 , a010 , a001 ),
1385- (a100 , a010 , a101 , a110 ),
1386- (a011 , a010 , a110 , a101 ),
1387- (a011 , a111 , a101 , a110 )]
1388-
1389- iel += nsubelements
1449+ elements , = np .where (
1450+ base_idx_tuples [:, axis ] == shape_m1 [axis ]- 1 )
1451+ box_face_to_elements [box_face ] = elements
1452+
1453+ else :
1454+ el_vertices = np .empty (
1455+ (nelements , nvertices_per_element ), dtype = np .int32 )
1456+ el_vertices [0 ::6 , :] = np .array ([a000 , a100 , a010 , a001 ]).T
1457+ el_vertices [1 ::6 , :] = np .array ([a101 , a100 , a001 , a010 ]).T
1458+ el_vertices [2 ::6 , :] = np .array ([a101 , a011 , a010 , a001 ]).T
1459+ el_vertices [3 ::6 , :] = np .array ([a100 , a010 , a101 , a110 ]).T
1460+ el_vertices [4 ::6 , :] = np .array ([a011 , a010 , a110 , a101 ]).T
1461+ el_vertices [5 ::6 , :] = np .array ([a011 , a111 , a101 , a110 ]).T
1462+
1463+ box_face_to_elements = {}
1464+ for box_face in box_faces :
1465+ side , axis = box_face
1466+ axis = int (axis )
1467+ if side == "-" :
1468+ box_elements , = np .where (base_idx_tuples [:, axis ] == 0 )
1469+ else :
1470+ box_elements , = np .where (
1471+ base_idx_tuples [:, axis ] == shape_m1 [axis ]- 1 )
1472+ if box_face == "-0" :
1473+ subelement_offsets = (0 , 2 )
1474+ if box_face == "+0" :
1475+ subelement_offsets = (3 , 5 )
1476+ if box_face == "-1" :
1477+ subelement_offsets = (0 , 1 )
1478+ if box_face == "+1" :
1479+ subelement_offsets = (4 , 5 )
1480+ if box_face == "-2" :
1481+ subelement_offsets = (0 , 3 )
1482+ if box_face == "+2" :
1483+ subelement_offsets = (2 , 5 )
1484+ box_face_to_elements [box_face ] = np .concatenate ([
1485+ 6 * box_elements + offset
1486+ for offset in subelement_offsets ])
1487+ else :
1488+ el_vertices = np .empty ((0 , nvertices_per_element ), dtype = np .int32 )
1489+ box_face_to_elements = {
1490+ box_face : np .array ([], dtype = np .int32 )
1491+ for box_face in box_faces }
13901492
13911493 else :
13921494 raise NotImplementedError ("box meshes of dimension %d" % dim )
@@ -1408,57 +1510,59 @@ def generate_box_mesh(
14081510
14091511 facial_adjacency_groups = None
14101512 face_vertex_indices_to_tags = {}
1411- boundary_tags = list (boundary_tag_to_face .keys ())
1412- nbnd_tags = len (boundary_tags )
14131513
1414- if nbnd_tags > 0 :
1514+ if boundary_tag_to_face :
14151515 vert_index_to_tuple = {
14161516 vertex_indices [itup ]: itup
14171517 for itup in np .ndindex (shape )}
14181518
1419- for ielem in range (0 , grp .nelements ):
1420- for ref_fvi in grp .face_vertex_indices ():
1421- fvi = grp .vertex_indices [ielem , ref_fvi ]
1519+ box_face_to_tags = {}
1520+ for tag , tagged_box_faces in boundary_tag_to_face .items ():
1521+ for box_face in tagged_box_faces :
1522+ if len (box_face ) != 2 :
1523+ raise ValueError (
1524+ f"face identifier '{ box_face } ' does not "
1525+ "consist of exactly two characters" )
1526+ side , axis = box_face
14221527 try :
1423- fvi_tuples = [vert_index_to_tuple [i ] for i in fvi ]
1424- except KeyError :
1425- # Happens for interior faces of "X" meshes because
1426- # midpoints aren't in vert_index_to_tuple. We don't
1427- # care about them.
1428- continue
1429-
1430- for tag in boundary_tags :
1431- # Need to map the correct face vertices to the boundary tags
1432- for face in boundary_tag_to_face [tag ]:
1433- if len (face ) != 2 :
1434- raise ValueError (
1435- "face identifier '%s' does not "
1436- "consist of exactly two characters" % face )
1437-
1438- side , axis = face
1439- try :
1440- axis = axes .index (axis )
1441- except ValueError as exc :
1442- raise ValueError (
1443- "unrecognized axis in face identifier "
1444- f"'{ face } '" ) from exc
1445- if axis >= dim :
1446- raise ValueError ("axis in face identifier '%s' "
1447- "does not exist in %dD" % (face , dim ))
1448-
1449- if side == "-" :
1450- vert_crit = 0
1451- elif side == "+" :
1452- vert_crit = shape [axis ] - 1
1453- else :
1454- raise ValueError ("first character of face identifier"
1455- " '%s' is not '+' or '-'" % face )
1456-
1457- if all (fvi_tuple [axis ] == vert_crit
1458- for fvi_tuple in fvi_tuples ):
1459- key = frozenset (fvi )
1460- face_vertex_indices_to_tags .setdefault (key ,
1461- []).append (tag )
1528+ axis = axes .index (axis )
1529+ except ValueError as exc :
1530+ raise ValueError (
1531+ "unrecognized axis in face identifier "
1532+ f"'{ box_face } '" ) from exc
1533+ if axis >= dim :
1534+ raise ValueError (f"axis in face identifier '{ box_face } ' "
1535+ f"does not exist in { dim } D" )
1536+ if side not in ("-" , "+" ):
1537+ raise ValueError ("first character of face identifier"
1538+ f" '{ box_face } ' is not '+' or '-'" )
1539+ box_face_to_tags .setdefault (f"{ side } { axis } " , []).append (tag )
1540+
1541+ for box_face , elements in box_face_to_elements .items ():
1542+ try :
1543+ tags = box_face_to_tags [box_face ]
1544+ except KeyError :
1545+ continue
1546+ side , axis = box_face
1547+ axis = int (axis )
1548+ if side == "-" :
1549+ vert_crit = 0
1550+ elif side == "+" :
1551+ vert_crit = shape [axis ] - 1
1552+ for ielem in elements :
1553+ for ref_fvi in grp .face_vertex_indices ():
1554+ fvi = grp .vertex_indices [ielem , ref_fvi ]
1555+ try :
1556+ fvi_tuples = [vert_index_to_tuple [i ] for i in fvi ]
1557+ except KeyError :
1558+ # Happens for interior faces of "X" meshes because
1559+ # midpoints aren't in vert_index_to_tuple. We don't
1560+ # care about them.
1561+ continue
1562+
1563+ if all (fvi_tuple [axis ] == vert_crit
1564+ for fvi_tuple in fvi_tuples ):
1565+ face_vertex_indices_to_tags [frozenset (fvi )] = tags
14621566
14631567 from meshmode .mesh import _compute_facial_adjacency_from_vertices
14641568 facial_adjacency_groups = _compute_facial_adjacency_from_vertices (
0 commit comments