Exemplo n.º 1
0
    def __init__(self, nodes, vertices, elements, connect):
        '''Instantiate the finite element mesh

        Parameters
        ----------
        nodes : list of int
            nodes[i] is the node label of the ith node
        vertices : ndarray of real
            vertices[i] are the nodal coordinates of the ith node
        elements : list of int
            elements[i] is the element label of the ith element
        connect : ndarray
            connect[i, j] is the jth node of the ith element

        '''
        # get nodal coordinates
        self.nodes = aslist(nodes)
        self.vertices = np.asarray(vertices)
        if len(self.vertices.shape) == 1:
            self.dimension = 1 # hard coded for now
        else:
            self.dimension = self.vertices.shape[1]

        # get element connectivity
        self.elements = aslist(elements)
        self.connect = np.asarray(connect)

        # Repository to hold element blocks, sidesets
        self.blocks = BlockRepository()
        self.nodesets = NodesetRepository()
Exemplo n.º 2
0
Arquivo: mesh.py Projeto: nrua/books
    def __init__(self, nodes, vertices, elements, connect):
        '''Instantiate the finite element mesh

        Parameters
        ----------
        nodes : list of int
            nodes[i] is the node label of the ith node
        vertices : ndarray of real
            vertices[i] are the nodal coordinates of the ith node
        elements : list of int
            elements[i] is the element label of the ith element
        connect : ndarray
            connect[i, j] is the jth node of the ith element

        '''
        # get nodal coordinates
        self.nodes = aslist(nodes)
        self.vertices = np.asarray(vertices)
        if len(self.vertices.shape) == 1:
            self.dimension = 1  # hard coded for now
        else:
            self.dimension = self.vertices.shape[1]

        # get element connectivity
        self.elements = aslist(elements)
        self.connect = np.asarray(connect)

        # Repository to hold element blocks, sidesets
        self.blocks = BlockRepository()
        self.nodesets = NodesetRepository()
Exemplo n.º 3
0
    def ElementBlock(self, name=None, elements=None):
        '''Assign elements to an element block'''
        if name is None:
            i = 1
            while True:
                name = 'Block-{0}'.format(i)
                if name not in self.blocks:
                    break
                i += 1
                if i > MAX_NUM_SETS:
                    raise ValueError('maximum number of blocks exceeded')
        if name in self.blocks:
            raise ValueError('{0}: element block already exists'.format(name))

        if isstr(elements):
            if elements.lower() == 'all':
                elements = [x for x in self.elements]

            elif elements.lower() == 'unassigned':
                assigned = []
                for elem_blk in self.element_blocks:
                    assigned.extend(elem_blk.elements)
                elements = list(set(self.elements) - set(assigned))
                elements = sorted(elements)

            else:
                raise ValueError('{0}: unrecognized option'.format(elements))

        else:
            elements = np.asarray(elements, dtype=np.int)

        elements = aslist(elements)
        try:
            elconn = self.connectivity(elements)
        except ValueError:
            raise ValueError('cannot assign elements of different '
                             'order to block {0}'.format(name))
        self.blocks[name] = ElementBlock(name, elements)
        return self.blocks[name]
Exemplo n.º 4
0
Arquivo: mesh.py Projeto: nrua/books
    def ElementBlock(self, name=None, elements=None):
        '''Assign elements to an element block'''
        if name is None:
            i = 1
            while True:
                name = 'Block-{0}'.format(i)
                if name not in self.blocks:
                    break
                i += 1
                if i > MAX_NUM_SETS:
                    raise ValueError('maximum number of blocks exceeded')
        if name in self.blocks:
            raise ValueError('{0}: element block already exists'.format(name))

        if isstr(elements):
            if elements.lower() == 'all':
                elements = [x for x in self.elements]

            elif elements.lower() == 'unassigned':
                assigned = []
                for elem_blk in self.element_blocks:
                    assigned.extend(elem_blk.elements)
                elements = list(set(self.elements) - set(assigned))
                elements = sorted(elements)

            else:
                raise ValueError('{0}: unrecognized option'.format(elements))

        else:
            elements = np.asarray(elements, dtype=np.int)

        elements = aslist(elements)
        try:
            elconn = self.connectivity(elements)
        except ValueError:
            raise ValueError('cannot assign elements of different '
                             'order to block {0}'.format(name))
        self.blocks[name] = ElementBlock(name, elements)
        return self.blocks[name]
Exemplo n.º 5
0
 def __init__(self, name, elements):
     self.name = name
     self.elements = aslist(elements)
Exemplo n.º 6
0
def solve_system(nodes, vertices, elements, connect, k, bcs, cfs,
                 num_dof_per_node=None, bc_method='default'):
    '''Computes the dependent variable of a linear system Ku = F by
    finite elements

    Parameters
    ----------
    nodes : list
        nodes[i] is the label of node i
    vertices : array
        vertices[i] is the nodal coordinates of the node labeled nodes[i]
    elements : list
        elements[i] is the label of element i
    connect :
        connect[i,j] is the jth node of element i
    k : list
        k[i] is the stiffness of the ith element
    bcs : list
        List of nodal boundary conditions. bcs[i] = (n, dof, bc) where n is
        the node number, dof is one of x or y, and bc is the magnitude of the
        nodal displacement
    cfs : list
        List of nodal forces.  cfs[i] = (n, dof, f) where n is the node
        number, dof is one of x or y, and f is the magnitude of the force

    Returns
    -------
    u : ndarray
        Nodal displacements
    r : ndarray
        Nodal reactions

    '''
    nodes = aslist(nodes)
    elements = aslist(elements)
    vertices = np.asarray(vertices)
    connect = np.asarray(connect)

    # Check that user input is consistent
    if len(vertices.shape) == 1:
        # we want vertices to have at least 1 column
        vertices = np.reshape(vertices, (vertices.shape[0], 1))
    num_node, num_dim = vertices.shape
    errors = 0
    num_elem = connect.shape[0]
    if num_elem != len(k):
        logging.error('wrong number of element stiffnesses')
        errors += 1
    if connect.shape[1] != 2:
        logging.error('expected 2 nodes per element')
        errors += 1
    nun = len(np.unique(connect))
    if nun != num_node:
        s = 'orphaned nodes in vertices'
        if nun < num_node:
            logging.error(s)
            errors += 1
        else:
            logging.warn(s)

    # make sure forces and boundary conditions not applied to same node
    bci = [bc[0] for bc in bcs]
    if any(cf[0] in bci for cf in cfs):
        logging.error('concentrated force and displacement '
                      'imposed on same node[s]')
        errors += 1

    # make sure that the system is stable
    if len(bcs) <= 0:
        logging.error('system requires at least one prescribed displacement '
                      'to be stable')
        errors += 1

    if errors:
        raise SystemExit('stopping due to previous errors')

    # total number of degrees of freedom
    num_dof_per_node = num_dof_per_node or num_dim
    num_dof = num_node * num_dof_per_node

    # Assemble stiffness
    K = np.zeros((num_dof, num_dof))
    nd = num_dof_per_node
    for (el, econn) in enumerate(connect):
        i = nodes.index(econn[0]) * num_dof_per_node
        j = nodes.index(econn[1]) * num_dof_per_node
        K[i:i+nd, i:i+nd] += k[el]
        K[j:j+nd, j:j+nd] += k[el]
        K[i:i+nd, j:j+nd] -= k[el]
        K[j:j+nd, i:i+nd] -= k[el]

    # Assemble force
    F = np.zeros(num_dof)
    for (node, dof, cf) in cfs:
        i = nodes.index(node) * num_dof_per_node + DOFS[dof.lower()]
        F[i] = cf

    # Apply boundary conditions on copies of K and F that we retain K and F
    # for later use.
    Kbc = np.array(K)
    Fbc = np.array(F)
    X = 1.e9 * np.amax(k)
    for (node, dof, bc) in bcs:
        i = nodes.index(node) * num_dof_per_node + DOFS[dof.lower()]
        if bc_method == 'default':
            # Default method - apply bcs such that the global stiffness
            # remains symmetric

            # Modify the RHS
            Fbc -= [Kbc[j, i] * bc for j in range(num_dof)]
            Fbc[i] = bc

            # Modify the stiffness
            Kbc[i, :] = 0
            Kbc[:, i] = 0
            Kbc[i, i] = 1

        elif bc_method == 'penalty':
            Kbc[i, i] = X
            Fbc[i] = X * bc

        else:
            raise ValueError('unknown bc_method {0}'.format(method))

    u = np.linalg.solve(Kbc, Fbc)
    r = np.dot(K, u) - F

    return u, r
Exemplo n.º 7
0
Arquivo: mesh.py Projeto: nrua/books
 def __init__(self, name, elements):
     self.name = name
     self.elements = aslist(elements)
Exemplo n.º 8
0
Arquivo: ifem.py Projeto: nrua/books
def solve_system(nodes,
                 vertices,
                 elements,
                 connect,
                 k,
                 bcs,
                 cfs,
                 num_dof_per_node=None,
                 bc_method='default'):
    '''Computes the dependent variable of a linear system Ku = F by
    finite elements

    Parameters
    ----------
    nodes : list
        nodes[i] is the label of node i
    vertices : array
        vertices[i] is the nodal coordinates of the node labeled nodes[i]
    elements : list
        elements[i] is the label of element i
    connect :
        connect[i,j] is the jth node of element i
    k : list
        k[i] is the stiffness of the ith element
    bcs : list
        List of nodal boundary conditions. bcs[i] = (n, dof, bc) where n is
        the node number, dof is one of x or y, and bc is the magnitude of the
        nodal displacement
    cfs : list
        List of nodal forces.  cfs[i] = (n, dof, f) where n is the node
        number, dof is one of x or y, and f is the magnitude of the force

    Returns
    -------
    u : ndarray
        Nodal displacements
    r : ndarray
        Nodal reactions

    '''
    nodes = aslist(nodes)
    elements = aslist(elements)
    vertices = np.asarray(vertices)
    connect = np.asarray(connect)

    # Check that user input is consistent
    if len(vertices.shape) == 1:
        # we want vertices to have at least 1 column
        vertices = np.reshape(vertices, (vertices.shape[0], 1))
    num_node, num_dim = vertices.shape
    errors = 0
    num_elem = connect.shape[0]
    if num_elem != len(k):
        logging.error('wrong number of element stiffnesses')
        errors += 1
    if connect.shape[1] != 2:
        logging.error('expected 2 nodes per element')
        errors += 1
    nun = len(np.unique(connect))
    if nun != num_node:
        s = 'orphaned nodes in vertices'
        if nun < num_node:
            logging.error(s)
            errors += 1
        else:
            logging.warn(s)

    # make sure forces and boundary conditions not applied to same node
    bci = [bc[0] for bc in bcs]
    if any(cf[0] in bci for cf in cfs):
        logging.error('concentrated force and displacement '
                      'imposed on same node[s]')
        errors += 1

    # make sure that the system is stable
    if len(bcs) <= 0:
        logging.error('system requires at least one prescribed displacement '
                      'to be stable')
        errors += 1

    if errors:
        raise SystemExit('stopping due to previous errors')

    # total number of degrees of freedom
    num_dof_per_node = num_dof_per_node or num_dim
    num_dof = num_node * num_dof_per_node

    # Assemble stiffness
    K = np.zeros((num_dof, num_dof))
    nd = num_dof_per_node
    for (el, econn) in enumerate(connect):
        i = nodes.index(econn[0]) * num_dof_per_node
        j = nodes.index(econn[1]) * num_dof_per_node
        K[i:i + nd, i:i + nd] += k[el]
        K[j:j + nd, j:j + nd] += k[el]
        K[i:i + nd, j:j + nd] -= k[el]
        K[j:j + nd, i:i + nd] -= k[el]

    # Assemble force
    F = np.zeros(num_dof)
    for (node, dof, cf) in cfs:
        i = nodes.index(node) * num_dof_per_node + DOFS[dof.lower()]
        F[i] = cf

    # Apply boundary conditions on copies of K and F that we retain K and F
    # for later use.
    Kbc = np.array(K)
    Fbc = np.array(F)
    X = 1.e9 * np.amax(k)
    for (node, dof, bc) in bcs:
        i = nodes.index(node) * num_dof_per_node + DOFS[dof.lower()]
        if bc_method == 'default':
            # Default method - apply bcs such that the global stiffness
            # remains symmetric

            # Modify the RHS
            Fbc -= [Kbc[j, i] * bc for j in range(num_dof)]
            Fbc[i] = bc

            # Modify the stiffness
            Kbc[i, :] = 0
            Kbc[:, i] = 0
            Kbc[i, i] = 1

        elif bc_method == 'penalty':
            Kbc[i, i] = X
            Fbc[i] = X * bc

        else:
            raise ValueError('unknown bc_method {0}'.format(method))

    u = np.linalg.solve(Kbc, Fbc)
    r = np.dot(K, u) - F

    return u, r