def is_in_element(position, element, allNodes): """ This function tests the inclusion of a point in an element. It calculates the form functions. If one if negative, it means that the point is outside. NOTE: We substract 1 from element.nodes since node ids start from 1, like element ids. example of allNodes array: allNodes = np.array(list(zip(flow.nodes_X[0],flow.nodes_Y[0]))) """ nodes_coords = allNodes[element.nodes - 1] p1, p2, p3 = nodes_coords[[0, 1, 2]] N1 = psi1(position, p1, p2, p3) N2 = psi2(position, p1, p2, p3) N3 = psi3(position, p1, p2, p3) # It suffices that one interpolation function takes a negative value to # deduce that the point is not inside the element. if (N1 >= 0) and (N2 >= 0) and (N3 >= 0): return True else: return False
def find_element_partrack(position, current_element, elements, allNodes): """ This function implements the particle tracer algorithm of Lohner and Ambrosiano (1990) """ nodes_coords = allNodes[current_element.nodes - 1] p1, p2, p3 = nodes_coords[[0, 1, 2]] N1 = psi1(position, p1, p2, p3) N2 = psi2(position, p1, p2, p3) N3 = psi3(position, p1, p2, p3) if (N1 >= 0) and (N2 >= 0) and (N3 >= 0): # In this case, the particle is still inside 'current_element'. return current_element else: # e.g. # If N3 has the most negative value, then index_smallest = 2. # Thus point_id_smallest (>= 0) is the farthest node from 'position'. index_smallest = np.argmin([N1, N2, N3]) point_id_smallest = current_element.nodes[index_smallest] next_element = find_opposite_neighbor(point_id_smallest, current_element, elements) return find_element_partrack(position, next_element, elements, allNodes)
def Psi6_y(*args): L1 = psi1(*args) L3 = psi3(*args) L1_y = psi1_y(*args) L3_y = psi3_y(*args) return 4 * (L3_y * L1 + L3 * L1_y)
def Psi6_x(*args): L1 = psi1(*args) L3 = psi3(*args) L1_x = psi1_x(*args) L3_x = psi3_x(*args) return 4 * (L3_x * L1 + L3 * L1_x)
def Psi5_y(*args): L2 = psi2(*args) L3 = psi3(*args) L2_y = psi2_y(*args) L3_y = psi3_y(*args) return 4 * (L2_y * L3 + L2 * L3_y)
def Psi5_x(*args): L2 = psi2(*args) L3 = psi3(*args) L2_x = psi2_x(*args) L3_x = psi3_x(*args) return 4 * (L2_x * L3 + L2 * L3_x)
def Psi3_y(*args): L3 = psi3(*args) L3_y = psi3_y(*args) return (4 * L3 - 1) * L3_y
def Psi3_x(*args): L3 = psi3(*args) L3_x = psi3_x(*args) return (4 * L3 - 1) * L3_x
def Psi3(*args): L3 = psi3(*args) return L3 * (2 * L3 - 1)
def Psi6(*args): L1 = psi1(*args) L3 = psi3(*args) return 4 * L3 * L1
def Psi5(*args): L2 = psi2(*args) L3 = psi3(*args) return 4 * L2 * L3