@@ -6,7 +6,7 @@ cimport numpy as np
66from libc.stdlib cimport malloc, free
77from libcpp.vector cimport vector
88from libcpp cimport bool
9- from numpy .math cimport INFINITY
9+ from libc .math cimport INFINITY
1010
1111from .tree cimport int_t, Tree as c_Tree, PyWrapper, Node, Edge, Face, Cell as c_Cell
1212from . cimport geom
@@ -15,6 +15,9 @@ import scipy.sparse as sp
1515import numpy as np
1616from .interputils_cython cimport _bisect_left, _bisect_right
1717
18+ class TreeMeshNotFinalizedError (RuntimeError ):
19+ """ Raise when a TreeMesh is not finalized."""
20+
1821
1922cdef class TreeCell:
2023 """ A class for defining cells within instances of :class:`~discretize.TreeMesh`.
@@ -1959,6 +1962,7 @@ cdef class _TreeMesh:
19591962 (n_cells, dim) numpy.ndarray of float
19601963 Gridded cell center locations
19611964 """
1965+ self ._error_if_not_finalized(" cell_centers" )
19621966 cdef np.float64_t[:, :] gridCC
19631967 cdef np.int64_t ii, ind, dim
19641968 if self ._cell_centers is None :
@@ -1984,6 +1988,7 @@ cdef class _TreeMesh:
19841988 (n_nodes, dim) numpy.ndarray of float
19851989 Gridded non-hanging node locations
19861990 """
1991+ self ._error_if_not_finalized(" nodes" )
19871992 cdef np.float64_t[:, :] gridN
19881993 cdef Node * node
19891994 cdef np.int64_t ii, ind, dim
@@ -2012,6 +2017,7 @@ cdef class _TreeMesh:
20122017 (n_hanging_nodes, dim) numpy.ndarray of float
20132018 Gridded hanging node locations
20142019 """
2020+ self ._error_if_not_finalized(" hanging_nodes" )
20152021 cdef np.float64_t[:, :] gridN
20162022 cdef Node * node
20172023 cdef np.int64_t ii, ind, dim
@@ -2038,6 +2044,7 @@ cdef class _TreeMesh:
20382044 (n_boundary_nodes, dim) numpy.ndarray of float
20392045 Gridded boundary node locations
20402046 """
2047+ self ._error_if_not_finalized(" boundary_nodes" )
20412048 nodes = self .nodes
20422049 x0, xF = self ._xs[0 ], self ._xs[- 1 ]
20432050 y0, yF = self ._ys[0 ], self ._ys[- 1 ]
@@ -2069,6 +2076,7 @@ cdef class _TreeMesh:
20692076 (n_cells, dim) numpy.ndarray of float
20702077 Gridded cell dimensions
20712078 """
2079+ self ._error_if_not_finalized(" h_gridded" )
20722080 if self ._h_gridded is not None :
20732081 return self ._h_gridded
20742082 cdef np.float64_t[:, :] gridCH
@@ -2097,6 +2105,7 @@ cdef class _TreeMesh:
20972105 (n_edges_x, dim) numpy.ndarray of float
20982106 Gridded locations of all non-hanging x-edges
20992107 """
2108+ self ._error_if_not_finalized(" edges_x" )
21002109 cdef np.float64_t[:, :] gridEx
21012110 cdef Edge * edge
21022111 cdef np.int64_t ii, ind, dim
@@ -2124,6 +2133,7 @@ cdef class _TreeMesh:
21242133 (n_hanging_edges_x, dim) numpy.ndarray of float
21252134 Gridded locations of all hanging x-edges
21262135 """
2136+ self ._error_if_not_finalized(" hanging_edges_x" )
21272137 cdef np.float64_t[:, :] gridhEx
21282138 cdef Edge * edge
21292139 cdef np.int64_t ii, ind, dim
@@ -2149,6 +2159,7 @@ cdef class _TreeMesh:
21492159 (n_edges_y, dim) numpy.ndarray of float
21502160 Gridded locations of all non-hanging y-edges
21512161 """
2162+ self ._error_if_not_finalized(" edges_y" )
21522163 cdef np.float64_t[:, :] gridEy
21532164 cdef Edge * edge
21542165 cdef np.int64_t ii, ind, dim
@@ -2176,6 +2187,7 @@ cdef class _TreeMesh:
21762187 (n_haning_edges_y, dim) numpy.ndarray of float
21772188 Gridded locations of all hanging y-edges
21782189 """
2190+ self ._error_if_not_finalized(" hanging_edges_y" )
21792191 cdef np.float64_t[:, :] gridhEy
21802192 cdef Edge * edge
21812193 cdef np.int64_t ii, ind, dim
@@ -2201,6 +2213,7 @@ cdef class _TreeMesh:
22012213 (n_edges_z, dim) numpy.ndarray of float
22022214 Gridded locations of all non-hanging z-edges
22032215 """
2216+ self ._error_if_not_finalized(" edges_z" )
22042217 cdef np.float64_t[:, :] gridEz
22052218 cdef Edge * edge
22062219 cdef np.int64_t ii, ind, dim
@@ -2228,6 +2241,7 @@ cdef class _TreeMesh:
22282241 (n_hanging_edges_z, dim) numpy.ndarray of float
22292242 Gridded locations of all hanging z-edges
22302243 """
2244+ self ._error_if_not_finalized(" hanging_edges_z" )
22312245 cdef np.float64_t[:, :] gridhEz
22322246 cdef Edge * edge
22332247 cdef np.int64_t ii, ind, dim
@@ -2255,6 +2269,7 @@ cdef class _TreeMesh:
22552269 (n_boundary_edges, dim) numpy.ndarray of float
22562270 Gridded boundary edge locations
22572271 """
2272+ self ._error_if_not_finalized(" boundary_edges" )
22582273 edges_x = self .edges_x
22592274 edges_y = self .edges_y
22602275 x0, xF = self ._xs[0 ], self ._xs[- 1 ]
@@ -2294,6 +2309,7 @@ cdef class _TreeMesh:
22942309 (n_faces_x, dim) numpy.ndarray of float
22952310 Gridded locations of all non-hanging x-faces
22962311 """
2312+ self ._error_if_not_finalized(" faces_x" )
22972313 if (self ._dim == 2 ): return self .edges_y
22982314
22992315 cdef np.float64_t[:, :] gridFx
@@ -2323,6 +2339,7 @@ cdef class _TreeMesh:
23232339 (n_faces_y, dim) numpy.ndarray of float
23242340 Gridded locations of all non-hanging y-faces
23252341 """
2342+ self ._error_if_not_finalized(" faces_y" )
23262343 if (self ._dim == 2 ): return self .edges_x
23272344 cdef np.float64_t[:, :] gridFy
23282345 cdef Face * face
@@ -2351,6 +2368,7 @@ cdef class _TreeMesh:
23512368 (n_faces_z, dim) numpy.ndarray of float
23522369 Gridded locations of all non-hanging z-faces
23532370 """
2371+ self ._error_if_not_finalized(" faces_z" )
23542372 if (self ._dim == 2 ): return self .cell_centers
23552373
23562374 cdef np.float64_t[:, :] gridFz
@@ -2380,6 +2398,7 @@ cdef class _TreeMesh:
23802398 (n_hanging_faces_x, dim) numpy.ndarray of float
23812399 Gridded locations of all hanging x-faces
23822400 """
2401+ self ._error_if_not_finalized(" hanging_faces_x" )
23832402 if (self ._dim == 2 ): return self .hanging_edges_y
23842403
23852404 cdef np.float64_t[:, :] gridFx
@@ -2407,6 +2426,7 @@ cdef class _TreeMesh:
24072426 (n_hanging_faces_y, dim) numpy.ndarray of float
24082427 Gridded locations of all hanging y-faces
24092428 """
2429+ self ._error_if_not_finalized(" hanging_faces_y" )
24102430 if (self ._dim == 2 ): return self .hanging_edges_x
24112431
24122432 cdef np.float64_t[:, :] gridhFy
@@ -2434,6 +2454,7 @@ cdef class _TreeMesh:
24342454 (n_hanging_faces_z, dim) numpy.ndarray of float
24352455 Gridded locations of all hanging z-faces
24362456 """
2457+ self ._error_if_not_finalized(" hanging_faces_z" )
24372458 if (self ._dim == 2 ): return np.array([])
24382459
24392460 cdef np.float64_t[:, :] gridhFz
@@ -2463,6 +2484,7 @@ cdef class _TreeMesh:
24632484 (n_boundary_faces, dim) numpy.ndarray of float
24642485 Gridded boundary face locations
24652486 """
2487+ self ._error_if_not_finalized(" boundary_faces" )
24662488 faces_x = self .faces_x
24672489 faces_y = self .faces_y
24682490 x0, xF = self ._xs[0 ], self ._xs[- 1 ]
@@ -2492,6 +2514,7 @@ cdef class _TreeMesh:
24922514 (n_boundary_faces, dim) numpy.ndarray of float
24932515 Outward normals of boundary faces
24942516 """
2517+ self ._error_if_not_finalized(" boundary_face_outward_normals" )
24952518 faces_x = self .faces_x
24962519 faces_y = self .faces_y
24972520 x0, xF = self ._xs[0 ], self ._xs[- 1 ]
@@ -2534,6 +2557,7 @@ cdef class _TreeMesh:
25342557 - *3D:* Returns the cell volumes
25352558
25362559 """
2560+ self ._error_if_not_finalized(" cell_volumes" )
25372561 cdef np.float64_t[:] vol
25382562 if self ._cell_volumes is None :
25392563 self ._cell_volumes = np.empty(self .n_cells, dtype = np.float64)
@@ -2558,6 +2582,7 @@ cdef class _TreeMesh:
25582582 respectively
25592583 - *3D:* returns the x, y and z-face areas in order
25602584 """
2585+ self ._error_if_not_finalized(" face_areas" )
25612586 if self ._dim == 2 and self ._face_areas is None :
25622587 self ._face_areas = np.r_[self .edge_lengths[self .n_edges_x:], self .edge_lengths[:self .n_edges_x]]
25632588 cdef np.float64_t[:] area
@@ -2600,6 +2625,7 @@ cdef class _TreeMesh:
26002625 - *2D:* returns the x-edge and y-edge lengths in order
26012626 - *3D:* returns the x, y and z-edge lengths in order
26022627 """
2628+ self ._error_if_not_finalized(" edge_lengths" )
26032629 cdef np.float64_t[:] edge_l
26042630 cdef Edge * edge
26052631 cdef int_t ind, offset
@@ -3564,6 +3590,7 @@ cdef class _TreeMesh:
35643590 ( n_total_faces_x, n_cells) scipy. sparse. csr_matrix
35653591 The stencil for the x-component of the cell gradient
35663592 """
3593+ self ._error_if_not_finalized(" stencil_cell_gradient_x" )
35673594 if getattr (self , ' _stencil_cell_gradient_x' , None ) is not None :
35683595 return self ._stencil_cell_gradient_x
35693596 cdef np.int64_t[:] I = np.zeros(2 * self .n_total_faces_x, dtype = np.int64)
@@ -3641,6 +3668,7 @@ cdef class _TreeMesh:
36413668 ( n_total_faces_y, n_cells) scipy. sparse. csr_matrix
36423669 The stencil for the y-component of the cell gradient
36433670 """
3671+ self ._error_if_not_finalized(" stencil_cell_gradient_y" )
36443672 if getattr (self , ' _stencil_cell_gradient_y' , None ) is not None :
36453673 return self ._stencil_cell_gradient_y
36463674
@@ -3719,6 +3747,7 @@ cdef class _TreeMesh:
37193747 ( n_total_faces_z, n_cells) scipy. sparse. csr_matrix
37203748 The stencil for the z-component of the cell gradient
37213749 """
3750+ self ._error_if_not_finalized(" stencil_cell_gradient_z" )
37223751 if getattr (self , ' _stencil_cell_gradient_z' , None ) is not None :
37233752 return self ._stencil_cell_gradient_z
37243753
@@ -5019,6 +5048,7 @@ cdef class _TreeMesh:
50195048
50205049 phi_f = Acf @ phi_c
50215050 """
5051+ self ._error_if_not_finalized(" average_cell_to_face" )
50225052 if self ._average_cell_to_face is not None :
50235053 return self ._average_cell_to_face
50245054 stacks = [self .average_cell_to_face_x, self .average_cell_to_face_y]
@@ -5079,6 +5109,7 @@ cdef class _TreeMesh:
50795109 in the x-direction. For boundary faces, nearest neighbor is used to extrapolate
50805110 the values.
50815111 """
5112+ self ._error_if_not_finalized(" average_cell_vector_to_face" )
50825113 if self ._average_cell_vector_to_face is not None :
50835114 return self ._average_cell_vector_to_face
50845115 stacks = [self .average_cell_to_face_x, self .average_cell_to_face_y]
@@ -5102,6 +5133,7 @@ cdef class _TreeMesh:
51025133 (n_faces_x, n_cells) scipy.sparse.csr_matrix
51035134 The scalar averaging operator from cell centers to x faces
51045135 """
5136+ self ._error_if_not_finalized(" average_cell_to_face_x" )
51055137 if self ._average_cell_to_face_x is not None :
51065138 return self ._average_cell_to_face_x
51075139 cdef np.int64_t[:] I = np.zeros(2 * self .n_total_faces_x, dtype = np.int64)
@@ -5218,6 +5250,7 @@ cdef class _TreeMesh:
52185250 (n_faces_y, n_cells) scipy.sparse.csr_matrix
52195251 The scalar averaging operator from cell centers to y faces
52205252 """
5253+ self ._error_if_not_finalized(" average_cell_to_face_y" )
52215254 if self ._average_cell_to_face_y is not None :
52225255 return self ._average_cell_to_face_y
52235256 cdef np.int64_t[:] I = np.zeros(2 * self .n_total_faces_y, dtype = np.int64)
@@ -5334,6 +5367,7 @@ cdef class _TreeMesh:
53345367 (n_faces_z, n_cells) scipy.sparse.csr_matrix
53355368 The scalar averaging operator from cell centers to z faces
53365369 """
5370+ self ._error_if_not_finalized(" average_cell_to_face_z" )
53375371 if self .dim == 2 :
53385372 raise Exception (' TreeMesh has no z-faces in 2D' )
53395373 if self ._average_cell_to_face_z is not None :
@@ -5424,6 +5458,7 @@ cdef class _TreeMesh:
54245458 scipy. sparse. csr_matrix
54255459 ( n_boundary_faces, n_faces) Projection matrix with shape
54265460 """
5461+ self ._error_if_not_finalized(" project_face_to_boundary_face" )
54275462 faces_x = self .faces_x
54285463 faces_y = self .faces_y
54295464
@@ -5459,6 +5494,7 @@ cdef class _TreeMesh:
54595494 ( n_boundary_edges, n_edges) scipy. sparse. csr_matrix
54605495 Projection matrix with shape
54615496 """
5497+ self ._error_if_not_finalized(" project_edge_to_boundary_edge" )
54625498 edges_x = self .edges_x
54635499 edges_y = self .edges_y
54645500
@@ -5501,6 +5537,7 @@ cdef class _TreeMesh:
55015537 ( n_boundary_nodes, n_nodes) scipy. sparse. csr_matrix
55025538 Projection matrix with shape
55035539 """
5540+ self ._error_if_not_finalized(" project_node_to_boundary_node" )
55045541 nodes = self .nodes
55055542 x0, xF = self ._xs[0 ], self ._xs[- 1 ]
55065543 y0, yF = self ._ys[0 ], self ._ys[- 1 ]
@@ -6964,6 +7001,17 @@ cdef class _TreeMesh:
69647001 """
69657002 return self .get_cells_in_aabb(* rectangle.reshape(self .dim, 2 ).T)
69667003
7004+ def _error_if_not_finalized (self , method: str ):
7005+ """
7006+ Raise error if mesh is not finalized.
7007+ """
7008+ if not self .finalized:
7009+ msg = (
7010+ f" `{type(self).__name__}.{method}` requires a finalized mesh. "
7011+ " Use the `finalize()` method to finalize it."
7012+ )
7013+ raise TreeMeshNotFinalizedError(msg)
7014+
69677015 def _require_ndarray_with_dim (self , name , arr , ndim = 1 , dtype = None , requirements = None ):
69687016 """ Returns an ndarray that has dim along it's last dimension, with ndim dims,
69697017
0 commit comments