Beispiel #1
0
def generate_finite_diff_mesh(mesh_size, num_free_nodes):
    """
    Generates a finite-difference mesh with the given size and number of free nodes.

    :param mesh_size: the mesh size
    :param num_free_nodes: the number of free nodes
    :return: the A and b matrices defining the mesh equation (Ax = b)
    """
    A = Matrix.empty(num_free_nodes, num_free_nodes)
    b = Matrix.empty(num_free_nodes, 1)
    for row in range(mesh_size - 3):
        for col in range(mesh_size - 1):
            node = row * (mesh_size - 1) + col
            A[node][node] = -4

            if row != 0:
                A[node][node - mesh_size + 1] = 1
            if 12 <= node <= 14:
                b[node][0] = -15
            else:
                A[node][node + mesh_size - 1] = 1

            # Right Neumann boundary
            if col == mesh_size - 2:
                A[node][node - 1] = 2
            else:
                if col != 0:
                    A[node][node - 1] = 1
                A[node][node + 1] = 1

    # Special nodes
    A[15][10] = 1
    A[15][15] = -4
    A[15][16] = 1
    A[15][17] = 1

    A[16][11] = 1
    A[16][15] = 1
    A[16][16] = -4
    A[16][18] = 1
    b[16][0] = -15

    A[17][15] = 2
    A[17][17] = -4
    A[17][18] = 1

    A[18][16] = 2
    A[18][17] = 1
    A[18][18] = -4
    b[18][0] = -15

    return A, b
Beispiel #2
0
def conjugate_gradient_solve(A, b, residual_vectors=None):
    """
    Solves the Ax = b matrix equation given by the given A and b matrices

    :param A: the A matrix
    :param b: the b matrix
    :param residual_vectors: the list to store the residual vectors in
    :return: the solved x vector
    """
    n = len(A)
    x = Matrix.empty(n, 1)
    r = b - A * x
    p = deepcopy(r)
    if residual_vectors is not None:
        residual_vectors.append(r)
    for _ in range(n):
        denom = p.transpose() * A * p
        alpha = (p.transpose() * r) / denom
        x = x + p * alpha.item()
        r = b - A * x
        beta = -(p.transpose() * A * r) / denom
        p = r + p * beta.item()
        if residual_vectors is not None:
            residual_vectors.append(r)
    return x
 def construct_phi(self):
     phi = Matrix.empty(self.mesh.num_rows, self.mesh.num_cols)
     for i in range(self.mesh.num_rows):
         y = self.mesh.get_y(i)
         for j in range(self.mesh.num_cols):
             x = self.mesh.get_x(j)
             boundary_pt = False
             for boundary in self.boundaries:
                 if boundary.contains_point(x, y):
                     boundary_pt = True
                     phi[i][j] = boundary.potential()
             if not boundary_pt:
                 phi[i][j] = self.guesser.guess(x, y)
     return phi
def find_disjoint_s_matrix(S1, S2):
    """
    Finds the disjoint S matrix given by the two provided local S matrices.

    :param S1: the first local S matrix
    :param S2: the second local S matrix
    :return: the disjoint S matrix
    """
    n = len(S1)
    S_dis = Matrix.empty(2 * n, 2 * n)
    for row in range(n):
        for col in range(n):
            S_dis[row][col] = S1[row][col]
            S_dis[row + n][col + n] = S2[row][col]
    return S_dis
Beispiel #5
0
def choleski_solve(A, b, half_bandwidth=None):
    """
    Solves an Ax = b matrix equation by Choleski decomposition.
    :param A: the A matrix
    :param b: the b matrix
    :param half_bandwidth: the half-bandwidth of the A matrix
    :return: the solved x vector
    """
    n = len(A[0])
    if half_bandwidth is None:
        elimination(A, b)
    else:
        elimination_banded(A, b, half_bandwidth)
    x = Matrix.empty(n, 1)
    back_substitution(A, x, b)
    return x
def find_local_s_matrix(triangle):
    """
    Finds the local S matrix for a finite-difference triangle.

    :param triangle: the finite-difference triangle
    :return: the local S matrix
    """
    x = triangle.x
    y = triangle.y
    S = Matrix.empty(3, 3)

    for i in range(3):
        for j in range(3):
            S[i][j] = ((y[(i + 1) % 3] - y[(i + 2) % 3]) *
                       (y[(j + 1) % 3] - y[(j + 2) % 3]) +
                       (x[(i + 1) % 3] - x[(i + 2) % 3]) *
                       (x[(j + 1) % 3] - x[(j + 2) % 3])) / (4 * triangle.area)

    return S
Beispiel #7
0
def compute_half_energy(S, mesh, mesh_size):
    """
    Computes the half-energy needed to compute the capacitance of the mesh.

    :param S: the S matrix
    :param mesh: the mesh
    :param mesh_size: the mesh size
    :return: the half-energy
    """
    U_con = Matrix.empty(4, 1)
    half_energy = 0
    for row in range(mesh_size - 1):
        for col in range(mesh_size - 1):
            node = row * mesh_size + (col + 1)  # 1-based
            if node < 28:
                U_con[0][0] = mesh[node + mesh_size]
                U_con[1][0] = mesh[node]
                U_con[2][0] = mesh[node + 1]
                U_con[3][0] = mesh[node + mesh_size + 1]
                half_energy_contribution = U_con.transpose() * S * U_con
                half_energy += half_energy_contribution[0][0]
    return half_energy
Beispiel #8
0
def create_incidence_matrix_mesh(cols, num_branches, num_horizontal_branches, num_nodes, num_vertical_branches):
    """
    Create the incidence matrix given by the resistive mesh with the given number of columns, number of branches,
    number of horizontal branches, number of nodes, and number of vertical branches.

    :param cols: the number of columns in the mesh
    :param num_branches: the number of branches in the mesh
    :param num_horizontal_branches: the number of horizontal branches in the mesh
    :param num_nodes: the number of nodes in the mesh
    :param num_vertical_branches: the number of vertical branches in the mesh
    :return: the incidence matrix (A)
    """
    A = Matrix.empty(num_nodes, num_branches)
    node_offset = -1
    for branch in range(num_horizontal_branches):
        if branch == num_horizontal_branches - cols + 1:
            A[branch + node_offset + 1][branch] = 1
        else:
            if branch % (cols - 1) == 0:
                node_offset += 1
            node_number = branch + node_offset
            A[node_number][branch] = -1
            A[node_number + 1][branch] = 1
    branch_offset = num_horizontal_branches
    node_offset = cols
    for branch in range(num_vertical_branches):
        if branch == num_vertical_branches - cols:
            node_offset -= 1
            A[branch][branch + branch_offset] = 1
        else:
            A[branch][branch + branch_offset] = 1
            A[branch + node_offset][branch + branch_offset] = -1
    if num_branches == 2:
        A[0][1] = -1
    else:
        A[cols - 1][num_branches - 1] = -1
    return A