def test_meshline_number_of_knots(): b1 = BSpline(1, 1, [0, 1, 2], [0, 1, 2]) m1 = Meshline(0, 2, constant_value=1, axis=0) m2 = Meshline(0, 2, constant_value=0.5, axis=1) assert m1.number_of_knots_contained(b1) == 1 assert m2.number_of_knots_contained(b1) == 0
def insert_line(self, meshline: Meshline, debug=False) -> None: """ Inserts a line in the mesh, splitting where necessary. Follows a four step procedure: Step 1: Test all BSplines against the new meshline, and if the meshline traverses the support, split the BSpline into B1 and B2. For both B1 and B2, check whether they are already in the set of previous BSplines. If they are not, add them to the list of new functions. Add the function that was split to the list of functions to remove. Step 2: Test all the new B-splines against all the meshlines already present in the mesh. They might have to be split further. Step 3: Check all elements of the mesh, and make sure that any previous elements traversed by the new meshline are split accordingly. Step 4: Make sure that all elements keep track of the basis functions they support, and that all basis functions keep track of the elements that support them. :param meshline: meshline to insert """ # step 0 # merge any existing meshlines, if the meshline already exists, we are done and can return early. meshline_already_exists, meshline = self.merge_meshlines(meshline) if meshline_already_exists: return # update the list of global tensorproduct knots if meshline.axis == 0: i = np.searchsorted(self.global_knots_u, meshline.constant_value, 'left') self.global_knots_u = np.insert(self.global_knots_u, i, meshline.constant_value) elif meshline.axis == 1: i = np.searchsorted(self.global_knots_v, meshline.constant_value, 'left') self.global_knots_v = np.insert(self.global_knots_v, i, meshline.constant_value) # step 1 # split B-splines against new meshline new_functions = [] functions_to_remove = [] for basis in self.S: if meshline.splits_basis(basis): if meshline.number_of_knots_contained( basis) < meshline.multiplicity: self.local_split(basis, meshline, functions_to_remove, new_functions) purged_S = [s for s in self.S if s not in functions_to_remove] self.S = purged_S # step 2 # split new B-splines against old meshlines self.meshlines.append(meshline) # for basis in new_functions: while len(new_functions) > 0: basis = new_functions.pop() split_more = False for m in self.meshlines: if m.splits_basis(basis): if m.number_of_knots_contained(basis) < m.multiplicity: split_more = True self.local_split(basis, m, functions_to_remove, new_functions) break if not split_more: self.S.append(basis) # step 3 # split all marked elements against new meshline new_elements = [] for element in self.M: if meshline.splits_element(element): new_elements.append( element.split(axis=meshline.axis, split_value=meshline.constant_value)) self.M += new_elements # step 4 # clean up, make sure all basis functions points to correct elements # make sure all elements point to correct basis functions # TODO: This implementation is preliminary, and possibly very slow. for element in self.M: element.supported_b_splines = [] for basis in self.S: basis.elements_of_support = [] for element in self.M: if basis.add_to_support_if_intersects(element): element.add_supported_b_spline(basis) # invalidate the element cache self.element_cache = None self.update_global_indices()