@@ -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+ i0 = np .arange (shape_m1 [0 ])
1271+
1272+ a0 = vertex_indices [i0 ]
1273+ a1 = vertex_indices [i0 + 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,76 @@ 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 ]):
1314-
1315- # c--d
1316- # | |
1317- # a--b
1318-
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 ]
13231322
1324- if is_tp :
1325- el_vertices [iel , :] = (a , b , c , d )
1326-
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-
1335- else :
1336- el_vertices [iel :iel + 2 , :] = [
1337- (a , b , c ),
1338- (d , c , b )]
1339-
1340- iel += nsubelements
1323+ if nelements > 0 :
1324+ base_idx_tuples = np .array (list (np .ndindex (shape_m1 )))
1325+
1326+ i0 = base_idx_tuples [:, 0 ]
1327+ j0 = base_idx_tuples [:, 1 ]
1328+
1329+ a00 = vertex_indices [i0 , j0 ]
1330+ a01 = vertex_indices [i0 , j0 + 1 ]
1331+ a10 = vertex_indices [i0 + 1 , j0 ]
1332+ a11 = vertex_indices [i0 + 1 , j0 + 1 ]
1333+
1334+ if is_tp :
1335+ el_vertices = np .array ([a00 , a10 , a01 , a11 ], dtype = np .int32 ).T
1336+
1337+ box_face_to_elements = {}
1338+ for box_face in box_faces :
1339+ side , axis = box_face
1340+ axis = int (axis )
1341+ idx_crit = 0 if side == "-" else shape_m1 [axis ] - 1
1342+ elements , = np .where (base_idx_tuples [:, axis ] == idx_crit )
1343+ box_face_to_elements [box_face ] = elements
1344+
1345+ elif mesh_type == "X" :
1346+ m = midpoint_indices [i0 , j0 ]
1347+ el_vertices = np .empty (
1348+ (nelements , nvertices_per_element ), dtype = np .int32 )
1349+ el_vertices [0 ::4 , :] = np .array ([a00 , a10 , m ]).T
1350+ el_vertices [1 ::4 , :] = np .array ([a10 , a11 , m ]).T
1351+ el_vertices [2 ::4 , :] = np .array ([a11 , a01 , m ]).T
1352+ el_vertices [3 ::4 , :] = np .array ([a01 , a00 , m ]).T
1353+
1354+ box_face_to_subelement_offset = {
1355+ "-0" : 3 ,
1356+ "+0" : 1 ,
1357+ "-1" : 0 ,
1358+ "+1" : 2 }
1359+
1360+ box_face_to_elements = {}
1361+ for box_face in box_faces :
1362+ side , axis = box_face
1363+ axis = int (axis )
1364+ idx_crit = 0 if side == "-" else shape_m1 [axis ] - 1
1365+ box_elements , = np .where (base_idx_tuples [:, axis ] == idx_crit )
1366+ box_face_to_elements [box_face ] = \
1367+ 4 * box_elements + box_face_to_subelement_offset [box_face ]
1368+
1369+ else :
1370+ el_vertices = np .empty (
1371+ (nelements , nvertices_per_element ), dtype = np .int32 )
1372+ el_vertices [0 ::2 , :] = np .array ([a00 , a10 , a01 ]).T
1373+ el_vertices [1 ::2 , :] = np .array ([a11 , a01 , a10 ]).T
1374+
1375+ side_to_subelement_offset = {
1376+ "-" : 0 ,
1377+ "+" : 1 }
1378+
1379+ box_face_to_elements = {}
1380+ for box_face in box_faces :
1381+ side , axis = box_face
1382+ axis = int (axis )
1383+ idx_crit = 0 if side == "-" else shape_m1 [axis ] - 1
1384+ box_elements , = np .where (base_idx_tuples [:, axis ] == idx_crit )
1385+ box_face_to_elements [box_face ] = \
1386+ 2 * box_elements + side_to_subelement_offset [side ]
1387+ else :
1388+ el_vertices = np .empty ((0 , nvertices_per_element ), dtype = np .int32 )
1389+ box_face_to_elements = {
1390+ box_face : np .array ([], dtype = np .int32 )
1391+ for box_face in box_faces }
13411392
13421393 elif dim == 3 :
13431394 if is_tp :
@@ -1355,38 +1406,68 @@ def generate_box_mesh(
13551406 raise ValueError (f"unsupported mesh type: '{ mesh_type } '" )
13561407
13571408 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 )
1379-
1380- 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
1409+
1410+ if nelements > 0 :
1411+ base_idx_tuples = np .array (list (np .ndindex (shape_m1 )))
1412+
1413+ i0 = base_idx_tuples [:, 0 ]
1414+ j0 = base_idx_tuples [:, 1 ]
1415+ k0 = base_idx_tuples [:, 2 ]
1416+
1417+ a000 = vertex_indices [i0 , j0 , k0 ]
1418+ a001 = vertex_indices [i0 , j0 , k0 + 1 ]
1419+ a010 = vertex_indices [i0 , j0 + 1 , k0 ]
1420+ a011 = vertex_indices [i0 , j0 + 1 , k0 + 1 ]
1421+ a100 = vertex_indices [i0 + 1 , j0 , k0 ]
1422+ a101 = vertex_indices [i0 + 1 , j0 , k0 + 1 ]
1423+ a110 = vertex_indices [i0 + 1 , j0 + 1 , k0 ]
1424+ a111 = vertex_indices [i0 + 1 , j0 + 1 , k0 + 1 ]
1425+
1426+ if is_tp :
1427+ el_vertices = np .array ([
1428+ a000 , a100 , a010 , a110 ,
1429+ a001 , a101 , a011 , a111 ], dtype = np .int32 ).T
1430+
1431+ box_face_to_elements = {}
1432+ for box_face in box_faces :
1433+ side , axis = box_face
1434+ axis = int (axis )
1435+ idx_crit = 0 if side == "-" else shape_m1 [axis ] - 1
1436+ elements , = np .where (base_idx_tuples [:, axis ] == idx_crit )
1437+ box_face_to_elements [box_face ] = elements
1438+
1439+ else :
1440+ el_vertices = np .empty (
1441+ (nelements , nvertices_per_element ), dtype = np .int32 )
1442+ el_vertices [0 ::6 , :] = np .array ([a000 , a100 , a010 , a001 ]).T
1443+ el_vertices [1 ::6 , :] = np .array ([a101 , a100 , a001 , a010 ]).T
1444+ el_vertices [2 ::6 , :] = np .array ([a101 , a011 , a010 , a001 ]).T
1445+ el_vertices [3 ::6 , :] = np .array ([a100 , a010 , a101 , a110 ]).T
1446+ el_vertices [4 ::6 , :] = np .array ([a011 , a010 , a110 , a101 ]).T
1447+ el_vertices [5 ::6 , :] = np .array ([a011 , a111 , a101 , a110 ]).T
1448+
1449+ box_face_to_subelement_offsets = {
1450+ "-0" : (0 , 2 ),
1451+ "+0" : (3 , 5 ),
1452+ "-1" : (0 , 1 ),
1453+ "+1" : (4 , 5 ),
1454+ "-2" : (0 , 3 ),
1455+ "+2" : (2 , 5 )}
1456+
1457+ box_face_to_elements = {}
1458+ for box_face in box_faces :
1459+ side , axis = box_face
1460+ axis = int (axis )
1461+ idx_crit = 0 if side == "-" else shape_m1 [axis ] - 1
1462+ box_elements , = np .where (base_idx_tuples [:, axis ] == idx_crit )
1463+ box_face_to_elements [box_face ] = np .concatenate ([
1464+ 6 * box_elements + offset
1465+ for offset in box_face_to_subelement_offsets [box_face ]])
1466+ else :
1467+ el_vertices = np .empty ((0 , nvertices_per_element ), dtype = np .int32 )
1468+ box_face_to_elements = {
1469+ box_face : np .array ([], dtype = np .int32 )
1470+ for box_face in box_faces }
13901471
13911472 else :
13921473 raise NotImplementedError ("box meshes of dimension %d" % dim )
@@ -1408,57 +1489,56 @@ def generate_box_mesh(
14081489
14091490 facial_adjacency_groups = None
14101491 face_vertex_indices_to_tags = {}
1411- boundary_tags = list (boundary_tag_to_face .keys ())
1412- nbnd_tags = len (boundary_tags )
14131492
1414- if nbnd_tags > 0 :
1493+ if boundary_tag_to_face :
14151494 vert_index_to_tuple = {
14161495 vertex_indices [itup ]: itup
14171496 for itup in np .ndindex (shape )}
14181497
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 ]
1498+ box_face_to_tags = {}
1499+ for tag , tagged_box_faces in boundary_tag_to_face .items ():
1500+ for box_face in tagged_box_faces :
1501+ if len (box_face ) != 2 :
1502+ raise ValueError (
1503+ f"face identifier '{ box_face } ' does not "
1504+ "consist of exactly two characters" )
1505+ side , axis = box_face
14221506 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 )
1507+ axis = axes .index (axis )
1508+ except ValueError as exc :
1509+ raise ValueError (
1510+ "unrecognized axis in face identifier "
1511+ f"'{ box_face } '" ) from exc
1512+ if axis >= dim :
1513+ raise ValueError (f"axis in face identifier '{ box_face } ' "
1514+ f"does not exist in { dim } D" )
1515+ if side not in ("-" , "+" ):
1516+ raise ValueError ("first character of face identifier"
1517+ f" '{ box_face } ' is not '+' or '-'" )
1518+ box_face_to_tags .setdefault (f"{ side } { axis } " , []).append (tag )
1519+
1520+ for box_face , elements in box_face_to_elements .items ():
1521+ try :
1522+ tags = box_face_to_tags [box_face ]
1523+ except KeyError :
1524+ continue
1525+ side , axis = box_face
1526+ axis = int (axis )
1527+ vert_crit = 0 if side == "-" else shape [axis ] - 1
1528+ for ielem in elements :
1529+ for ref_fvi in grp .face_vertex_indices ():
1530+ fvi = grp .vertex_indices [ielem , ref_fvi ]
1531+ try :
1532+ fvi_tuples = [vert_index_to_tuple [i ] for i in fvi ]
1533+ except KeyError :
1534+ # Happens for interior faces of "X" meshes because
1535+ # midpoints aren't in vert_index_to_tuple. We don't
1536+ # care about them.
1537+ continue
1538+
1539+ if all (fvi_tuple [axis ] == vert_crit
1540+ for fvi_tuple in fvi_tuples ):
1541+ face_vertex_indices_to_tags [frozenset (fvi )] = tags
14621542
14631543 from meshmode .mesh import _compute_facial_adjacency_from_vertices
14641544 facial_adjacency_groups = _compute_facial_adjacency_from_vertices (
0 commit comments