11# distutils: language=c++
22# cython: embedsignature=True, language_level=3
33# cython: linetrace=True
4+ # cython: freethreading_compatible=True
45cimport cython
56cimport numpy as np
67from libc.stdlib cimport malloc, free
@@ -359,6 +360,7 @@ cdef class _TreeMesh:
359360 cdef int_t[3 ] ls
360361 cdef int _finalized
361362 cdef bool _diagonal_balance
363+ cdef cython.pymutex _tree_modify_lock
362364
363365 cdef double [:] _xs, _ys, _zs
364366 cdef double [:] _origin
@@ -546,9 +548,12 @@ cdef class _TreeMesh:
546548
547549 # Wrapping function so it can be called in c++
548550 cdef void * func_ptr = < void * > function
549- self .wrapper.set(func_ptr, _evaluate_func)
550- # Then tell c++ to build the tree
551- self .tree.refine_function(self .wrapper, diag_balance)
551+
552+
553+ with self ._tree_modify_lock:
554+ self .wrapper.set(func_ptr, _evaluate_func)
555+ # Then tell c++ to build the tree
556+ self .tree.refine_function(self .wrapper, diag_balance)
552557 if finalize:
553558 self .finalize()
554559
@@ -631,7 +636,9 @@ cdef class _TreeMesh:
631636 for i in range (n_balls):
632637 ball = geom.Ball(self ._dim, & cs[i_c, 0 ], rs[i_r])
633638 l = _wrap_levels(ls[i_l], max_level)
634- self .tree.refine_geom(ball, l, diag_balance)
639+
640+ with self ._tree_modify_lock:
641+ self .tree.refine_geom(ball, l, diag_balance)
635642
636643 i_c += cs_step
637644 i_r += rs_step
@@ -715,7 +722,8 @@ cdef class _TreeMesh:
715722 for i in range (n_boxes):
716723 box = geom.Box(self ._dim, & x0[i_x0, 0 ], & x1[i_x1, 0 ])
717724 l = _wrap_levels(ls[i_l], max_level)
718- self .tree.refine_geom(box, l, diag_balance)
725+ with self ._tree_modify_lock:
726+ self .tree.refine_geom(box, l, diag_balance)
719727
720728 i_x0 += x0_step
721729 i_x1 += x1_step
@@ -792,7 +800,8 @@ cdef class _TreeMesh:
792800 for i in range (n_segments):
793801 line = geom.Line(self ._dim, & line_nodes[i_line, 0 ], & line_nodes[i_line+ 1 , 0 ])
794802 l = _wrap_levels(ls[i_l], max_level)
795- self .tree.refine_geom(line, l, diag_balance)
803+ with self ._tree_modify_lock:
804+ self .tree.refine_geom(line, l, diag_balance)
796805
797806 i_line += line_step
798807 i_l += l_step
@@ -875,7 +884,8 @@ cdef class _TreeMesh:
875884 for i in range (n_planes):
876885 plane = geom.Plane(self ._dim, & x_0s[i_o, 0 ], & norms[i_n, 0 ])
877886 l = _wrap_levels(ls[i_l], max_level)
878- self .tree.refine_geom(plane, l, diag_balance)
887+ with self ._tree_modify_lock:
888+ self .tree.refine_geom(plane, l, diag_balance)
879889
880890 i_o += origin_step
881891 i_n += normal_step
@@ -953,7 +963,8 @@ cdef class _TreeMesh:
953963 for i in range (n_triangles):
954964 triang = geom.Triangle(self ._dim, & tris[i_tri, 0 , 0 ], & tris[i_tri, 1 , 0 ], & tris[i_tri, 2 , 0 ])
955965 l = _wrap_levels(ls[i_l], max_level)
956- self .tree.refine_geom(triang, l, diag_balance)
966+ with self ._tree_modify_lock:
967+ self .tree.refine_geom(triang, l, diag_balance)
957968
958969 i_tri += tri_step
959970 i_l += l_step
@@ -1048,7 +1059,8 @@ cdef class _TreeMesh:
10481059 for i in range (n_triangles):
10491060 vert_prism = geom.VerticalTriangularPrism(self ._dim, & tris[i_tri, 0 , 0 ], & tris[i_tri, 1 , 0 ], & tris[i_tri, 2 , 0 ], hs[i_h])
10501061 l = _wrap_levels(ls[i_l], max_level)
1051- self .tree.refine_geom(vert_prism, l, diag_balance)
1062+ with self ._tree_modify_lock:
1063+ self .tree.refine_geom(vert_prism, l, diag_balance)
10521064
10531065 i_tri += tri_step
10541066 i_h += h_step
@@ -1133,7 +1145,9 @@ cdef class _TreeMesh:
11331145 for i in range (n_triangles):
11341146 l = _wrap_levels(ls[i_l], max_level)
11351147 tet = geom.Tetrahedron(self ._dim, & tris[i_tri, 0 , 0 ], & tris[i_tri, 1 , 0 ], & tris[i_tri, 2 , 0 ], & tris[i_tri, 3 , 0 ])
1136- self .tree.refine_geom(tet, l, diag_balance)
1148+
1149+ with self ._tree_modify_lock:
1150+ self .tree.refine_geom(tet, l, diag_balance)
11371151
11381152 i_tri += tri_step
11391153 i_l += l_step
@@ -1192,7 +1206,8 @@ cdef class _TreeMesh:
11921206
11931207 for i in range (ls.shape[0 ]):
11941208 l = _wrap_levels(ls[i_l], max_level)
1195- self .tree.insert_cell(& cs[i_p, 0 ], l, diagonal_balance)
1209+ with self ._tree_modify_lock:
1210+ self .tree.insert_cell(& cs[i_p, 0 ], l, diagonal_balance)
11961211
11971212 i_l += l_step
11981213 i_p += p_step
@@ -1208,10 +1223,11 @@ cdef class _TreeMesh:
12081223 operators. When finalized, mesh refinement is no longer enabled.
12091224
12101225 """
1211- if not self ._finalized:
1212- self .tree.finalize_lists()
1213- self .tree.number()
1214- self ._finalized= True
1226+ with self ._tree_modify_lock:
1227+ if not self ._finalized:
1228+ self .tree.finalize_lists()
1229+ self .tree.number()
1230+ self ._finalized= True
12151231
12161232 @property
12171233 def finalized (self ):
@@ -1228,7 +1244,9 @@ cdef class _TreeMesh:
12281244 bool
12291245 Returns *True* if finalized, *False* otherwise
12301246 """
1231- return self ._finalized
1247+ with self ._tree_modify_lock:
1248+ val = self ._finalized
1249+ return val
12321250
12331251 @property
12341252 @ cython.boundscheck (False )
@@ -1248,7 +1266,9 @@ cdef class _TreeMesh:
12481266
12491267 def number (self ):
12501268 """ Number the cells, nodes, faces, and edges of the TreeMesh."""
1251- self .tree.number()
1269+
1270+ with self ._tree_modify_lock:
1271+ self .tree.number()
12521272
12531273 def get_containing_cells (self , points ):
12541274 """ Return the cells containing the given points.
@@ -1453,52 +1473,53 @@ cdef class _TreeMesh:
14531473 if dim == 3 :
14541474 shift[2 ] = self ._origin[2 ] - self ._zs[0 ]
14551475
1456- for i in range (self ._xs.shape[0 ]):
1457- self ._xs[i] += shift[0 ]
1458- for i in range (self ._ys.shape[0 ]):
1459- self ._ys[i] += shift[1 ]
1460- if dim == 3 :
1461- for i in range (self ._zs.shape[0 ]):
1462- self ._zs[i] += shift[2 ]
1463-
1464- # update the locations of all of the items
1465- self .tree.shift_cell_centers(& shift[0 ])
1466-
1467- for itN in self .tree.nodes:
1468- node = itN.second
1469- for i in range (dim):
1470- node.location[i] += shift[i]
1476+ with self ._tree_modify_lock:
1477+ for i in range (self ._xs.shape[0 ]):
1478+ self ._xs[i] += shift[0 ]
1479+ for i in range (self ._ys.shape[0 ]):
1480+ self ._ys[i] += shift[1 ]
1481+ if dim == 3 :
1482+ for i in range (self ._zs.shape[0 ]):
1483+ self ._zs[i] += shift[2 ]
14711484
1472- for itE in self .tree.edges_x:
1473- edge = itE.second
1474- for i in range (dim):
1475- edge.location[i] += shift[i]
1485+ # update the locations of all of the items
1486+ self .tree.shift_cell_centers(& shift[0 ])
14761487
1477- for itE in self .tree.edges_y :
1478- edge = itE .second
1479- for i in range (dim):
1480- edge .location[i] += shift[i]
1488+ for itN in self .tree.nodes :
1489+ node = itN .second
1490+ for i in range (dim):
1491+ node .location[i] += shift[i]
14811492
1482- if dim == 3 :
1483- for itE in self .tree.edges_z:
1493+ for itE in self .tree.edges_x:
14841494 edge = itE.second
14851495 for i in range (dim):
14861496 edge.location[i] += shift[i]
14871497
1488- for itF in self .tree.faces_x:
1489- face = itF.second
1490- for i in range (dim):
1491- face.location[i] += shift[i]
1492-
1493- for itF in self .tree.faces_y:
1494- face = itF.second
1498+ for itE in self .tree.edges_y:
1499+ edge = itE.second
14951500 for i in range (dim):
1496- face .location[i] += shift[i]
1501+ edge .location[i] += shift[i]
14971502
1498- for itF in self .tree.faces_z:
1499- face = itF.second
1500- for i in range (dim):
1501- face.location[i] += shift[i]
1503+ if dim == 3 :
1504+ for itE in self .tree.edges_z:
1505+ edge = itE.second
1506+ for i in range (dim):
1507+ edge.location[i] += shift[i]
1508+
1509+ for itF in self .tree.faces_x:
1510+ face = itF.second
1511+ for i in range (dim):
1512+ face.location[i] += shift[i]
1513+
1514+ for itF in self .tree.faces_y:
1515+ face = itF.second
1516+ for i in range (dim):
1517+ face.location[i] += shift[i]
1518+
1519+ for itF in self .tree.faces_z:
1520+ face = itF.second
1521+ for i in range (dim):
1522+ face.location[i] += shift[i]
15021523 # clear out all cached grids
15031524 self ._cell_centers = None
15041525 self ._nodes = None
@@ -7046,7 +7067,6 @@ cdef class _TreeMesh:
70467067 )
70477068 return np.require(arr, dtype = dtype, requirements = requirements)
70487069
7049-
70507070def _check_first_dim_broadcast (**kwargs ):
70517071 """ Perform a check to make sure that the first dimensions of the inputs will broadcast."""
70527072 n_items = 1
0 commit comments