-
Notifications
You must be signed in to change notification settings - Fork 45
Open
Labels
scalabilityRelated to scalability & performance effortsRelated to scalability & performance efforts
Milestone
Description
Below are timings taken across multiple grid resolutions on a single NCAR Derecho CPU node.
| Resolution | Nodes | Faces | Edges | Grid Load Time (s) | face_edges_xyz (s) |
|---|---|---|---|---|---|
| 30km | 1,310,720 | 655,362 | 1,966,080 | 1.921 | 0.498 |
| 15km | 5,242,880 | 2,621,442 | 7,864,320 | 7.458 | 2.213 |
| 7.5km | 20,971,520 | 10,485,762 | 31,457,280 | 27.46 | 6.764 |
| 3.75km | 83,886,080 | 41,943,042 | 125,829,120 | 113.993 | 28.683 |
While the performance here is not bad, it is noticeably slow for the higher resolutions.
@hongyuchen1030 pointed out that we could consider caching this variable for re-use, especially since multiple calls to zonal average could take advantage of this. There is an informative discussion about this in #1180
The current implementation only relies on the face_node_connectivity and uses it to derive the edge information. If the edge_node_connectivity and face_edge_connectivity are available, it may be more efficient to use these to index our coordinates.
Lines 141 to 259 in 3b7e8c4
| def _get_cartesian_face_edge_nodes( | |
| face_node_conn, n_face, n_max_face_edges, node_x, node_y, node_z | |
| ): | |
| """Construct an array to hold the edge Cartesian coordinates connectivity | |
| for multiple faces in a grid. | |
| Parameters | |
| ---------- | |
| face_node_conn : np.ndarray | |
| An array of shape (n_face, n_max_face_edges) containing the node indices for each face. Accessed through `grid.face_node_connectivity.value`. | |
| n_face : int | |
| The number of faces in the grid. Accessed through `grid.n_face`. | |
| n_max_face_edges : int | |
| The maximum number of edges for any face in the grid. Accessed through `grid.n_max_face_edges`. | |
| node_x : np.ndarray | |
| An array of shape (n_nodes,) containing the x-coordinate values of the nodes. Accessed through `grid.node_x`. | |
| node_y : np.ndarray | |
| An array of shape (n_nodes,) containing the y-coordinate values of the nodes. Accessed through `grid.node_y`. | |
| node_z : np.ndarray | |
| An array of shape (n_nodes,) containing the z-coordinate values of the nodes. Accessed through `grid.node_z`. | |
| Returns | |
| ------- | |
| face_edges_cartesian : np.ndarray | |
| An array of shape (n_face, n_max_face_edges, 2, 3) containing the Cartesian coordinates of the edges | |
| for each face. It might contain dummy values if the grid has holes. | |
| Examples | |
| -------- | |
| >>> face_node_conn = np.array( | |
| ... [ | |
| ... [0, 1, 2, 3, 4], | |
| ... [0, 1, 3, 4, INT_FILL_VALUE], | |
| ... [0, 1, 3, INT_FILL_VALUE, INT_FILL_VALUE], | |
| ... ] | |
| ... ) | |
| >>> n_face = 3 | |
| >>> n_max_face_edges = 5 | |
| >>> node_x = np.array([0, 1, 1, 0, 1, 0]) | |
| >>> node_y = np.array([0, 0, 1, 1, 2, 2]) | |
| >>> node_z = np.array([0, 0, 0, 0, 1, 1]) | |
| >>> _get_cartesian_face_edge_nodes( | |
| ... face_node_conn, n_face, n_max_face_edges, node_x, node_y, node_z | |
| ... ) | |
| array([[[[ 0, 0, 0], | |
| [ 1, 0, 0]], | |
| [[ 1, 0, 0], | |
| [ 1, 1, 0]], | |
| [[ 1, 1, 0], | |
| [ 0, 1, 0]], | |
| [[ 0, 1, 0], | |
| [ 1, 2, 1]], | |
| [[ 1, 2, 1], | |
| [ 0, 0, 0]]], | |
| [[[ 0, 0, 0], | |
| [ 1, 0, 0]], | |
| [[ 1, 0, 0], | |
| [ 0, 1, 0]], | |
| [[ 0, 1, 0], | |
| [ 1, 2, 1]], | |
| [[ 1, 2, 1], | |
| [ 0, 0, 0]], | |
| [[INT_FILL_VALUE, INT_FILL_VALUE, INT_FILL_VALUE], | |
| [INT_FILL_VALUE, INT_FILL_VALUE, INT_FILL_VALUE]]], | |
| [[[ 0, 0, 0], | |
| [ 1, 0, 0]], | |
| [[ 1, 0, 0], | |
| [ 0, 1, 0]], | |
| [[ 0, 1, 0], | |
| [ 0, 0, 0]], | |
| [[INT_FILL_VALUE, INT_FILL_VALUE, INT_FILL_VALUE], | |
| [INT_FILL_VALUE, INT_FILL_VALUE, INT_FILL_VALUE]], | |
| [[INT_FILL_VALUE, INT_FILL_VALUE, INT_FILL_VALUE], | |
| [INT_FILL_VALUE, INT_FILL_VALUE, INT_FILL_VALUE]]]]) | |
| """ | |
| # Shift node connections to create edge connections | |
| face_node_conn_shift = np.roll(face_node_conn, -1, axis=1) | |
| # Construct edge connections by combining original and shifted node connections | |
| face_edge_conn = np.array([face_node_conn, face_node_conn_shift]).T.swapaxes(0, 1) | |
| # swap the first occurrence of INT_FILL_VALUE with the last value in each sub-array | |
| face_edge_conn = _swap_first_fill_value_with_last(face_edge_conn) | |
| # Get the indices of the nodes from face_edge_conn | |
| face_edge_conn_flat = face_edge_conn.reshape(-1) | |
| valid_mask = face_edge_conn_flat != INT_FILL_VALUE | |
| # Get the valid node indices | |
| valid_edges = face_edge_conn_flat[valid_mask] | |
| # Create an array to hold the Cartesian coordinates of the edges | |
| face_edges_cartesian = np.full( | |
| (len(face_edge_conn_flat), 3), INT_FILL_VALUE, dtype=float | |
| ) | |
| # Fill the array with the Cartesian coordinates of the edges | |
| face_edges_cartesian[valid_mask, 0] = node_x[valid_edges] | |
| face_edges_cartesian[valid_mask, 1] = node_y[valid_edges] | |
| face_edges_cartesian[valid_mask, 2] = node_z[valid_edges] | |
| return face_edges_cartesian.reshape(n_face, n_max_face_edges, 2, 3) |
Metadata
Metadata
Assignees
Labels
scalabilityRelated to scalability & performance effortsRelated to scalability & performance efforts
Type
Projects
Status
🏗 In progress