def create_boundary_problem_matrix(self, omega): # full dof number self.map_dofs() num_dof = len(self.dof_mapping) # number of nodes node_no = len(self.nodes) # number of internal dofs internal_dof_no = np.sum(e.num_degrees_of_freedom() for e in self.elements) # number of terminals terminal_no = np.sum(e.num_terminals() for e in self.elements) # dynamic equations reflect the element's IV characteristic dynamic_equation_no = terminal_no + internal_dof_no # kinetic equations are Kirchhof's law that the sum of nodal currents is zero kinetic_equation_no = node_no num_equations = dynamic_equation_no + kinetic_equation_no boundary_condition_matrix = np.zeros((num_equations, num_dof), dtype=complex) # filling dynamic equations equation_id = 0 current_offset = 0 internal_dof_offset = 0 for e_id, e in enumerate(self.elements): equations = e.boundary_condition(omega) for element_equation_id in range(equations.shape[0]): equation = equations[element_equation_id, :] for terminal_id, terminal_node in enumerate( self.terminal_node_mapping[e_id]): node_id = self.nodes.index(terminal_node) boundary_condition_matrix[equation_id, node_id] = equation[ terminal_id] # nodal voltages boundary_condition_matrix[ equation_id, node_no + current_offset + terminal_id] = equation[ terminal_id + e.num_terminals()] # nodal current for internal_dof_id in range(e.num_degrees_of_freedom()): boundary_condition_matrix[ equation_id, node_no + terminal_no + internal_dof_offset + internal_dof_id] = equation[2 * e.num_terminals() + internal_dof_id] equation_id += 1 internal_dof_offset += e.num_degrees_of_freedom() current_offset += e.num_terminals() full_terminal_id = 0 # filling kinetic equations for e_id, e in enumerate(self.elements): for terminal_id, node in enumerate( self.terminal_node_mapping[e_id]): boundary_condition_matrix[dynamic_equation_no + self.nodes.index(node), node_no + full_terminal_id] = 1 full_terminal_id += 1 return boundary_condition_matrix
def get_element_dynamic_equations(self, element: TLSystemElement): e_id = self.elements.index(element) offset = np.sum(e.num_terminals() + e.num_degrees_of_freedom() for e in self.elements[:e_id]) return np.arange( offset, offset + element.num_terminals() + element.num_degrees_of_freedom())
def map_dofs(self): # count nodes self.dof_mapping = [n for n in self.nodes] # nodal voltages self.dof_mapping.extend([(e_id, p_id) for e_id, e in enumerate(self.elements) for p_id in range(e.num_terminals())]) # currents incident into each terminal self.dof_mapping.extend([ (e_id, int_dof_id) for e_id, e in enumerate(self.elements) for int_dof_id in range(e.num_degrees_of_freedom()) ])