def strainGLO(IELCON, UU, ne, COORD, elements):
    """Compute the strain solution for all the elements

    Computes the strain solution for all the elements
    in the domain and the physical coordinates of the complete
    domain integration points. It then assembles all the element strains
    into a global strains vector EG[].

    Parameters
    ----------
    IELCON : ndarray (int)
      Array with the nodes numbers for each element.
    UU : ndarray (float)
      Array with the displacements. This one contains both, the
      computed and imposed values.
    ne : int
      Number of elements.
    COORD : ndarray (float).
      Array with nodes coordinates.
    elements : ndarray (int)
      Array with the node number for the nodes that correspond to each
      element.

    Returns
    -------
    EG : ndarray (float)
      Array that contains the strain solution for each integration
      point in physical coordinates.
    XS : ndarray (float)
      Array with the coordinates of the integration points.

    """
    iet = elements[0, 1]
    ndof, nnodes, ngpts = fe.eletype(iet)

    XS = np.zeros([ngpts*ne, 2], dtype=np.float)
    elcoor = np.zeros([nnodes, 2], dtype=np.float)
    EG = np.zeros([ngpts*ne, 3], dtype=np.float)
    ul = np.zeros([ndof], dtype=np.float)
    for i in range(ne):
        for j in range(nnodes):
            elcoor[j, 0] = COORD[IELCON[i, j], 0]
            elcoor[j, 1] = COORD[IELCON[i, j], 1]
        for j in range(ndof):
            ul[j] = UU[i, j]
        if iet == 1:
            epsG, xl = fe.str_el4(elcoor, ul)
        elif iet == 2:
            epsG, xl = fe.str_el6(elcoor, ul)
        elif iet == 3:
            epsG, xl = fe.str_el3(elcoor, ul)

        for j in range(ngpts):
            XS[ngpts*i + j, 0] = xl[j, 0]
            XS[ngpts*i + j, 1] = xl[j, 1]
            for k in range(3):
                EG[ngpts*i + j, k] = epsG[j, k]

    return EG, XS
def strainGLO(IELCON, UU, ne, COORD, elements):
    """Compute the strain solution for all the elements

    Computes the strain solution for all the elements
    in the domain and the physical coordinates of the complete
    domain integration points. It then assembles all the element strains
    into a global strains vector EG[].

    Parameters
    ----------
    IELCON : ndarray (int)
      Array with the nodes numbers for each element.
    UU : ndarray (float)
      Array with the displacements. This one contains both, the
      computed and imposed values.
    ne : int
      Number of elements.
    COORD : ndarray (float).
      Array with nodes coordinates.
    elements : ndarray (int)
      Array with the node number for the nodes that correspond to each
      element.

    Returns
    -------
    EG : ndarray (float)
      Array that contains the strain solution for each integration
      point in physical coordinates.
    XS : ndarray (float)
      Array with the coordinates of the integration points.

    """
    iet = elements[0, 1]
    ndof, nnodes, ngpts = fe.eletype(iet)

    XS = np.zeros([ngpts * ne, 2], dtype=np.float)
    elcoor = np.zeros([nnodes, 2], dtype=np.float)
    EG = np.zeros([ngpts * ne, 3], dtype=np.float)
    ul = np.zeros([ndof], dtype=np.float)
    for i in range(ne):
        for j in range(nnodes):
            elcoor[j, 0] = COORD[IELCON[i, j], 0]
            elcoor[j, 1] = COORD[IELCON[i, j], 1]
        for j in range(ndof):
            ul[j] = UU[i, j]
        if iet == 1:
            epsG, xl = fe.str_el4(elcoor, ul)
        elif iet == 2:
            epsG, xl = fe.str_el6(elcoor, ul)
        elif iet == 3:
            epsG, xl = fe.str_el3(elcoor, ul)

        for j in range(ngpts):
            XS[ngpts * i + j, 0] = xl[j, 0]
            XS[ngpts * i + j, 1] = xl[j, 1]
            for k in range(3):
                EG[ngpts * i + j, k] = epsG[j, k]

    return EG, XS
def strain_nodes(IELCON, UU, ne, COORD, elements, mats):
    """Compute averaged strains and stresses at nodes
    
    First, the variable is extrapolated from the Gauss
    point to nodes for each element. Then, these values are averaged
    according to the number of element that share that node. The theory
    for this technique can be found in [1]_.
    
    Parameters
    ----------
    IELCON : ndarray (int)
      Array with the nodes numbers for each element.
    UU : ndarray (float)
      Array with the displacements. This one contains both, the
      computed and imposed values.
    ne : int
      Number of elements.
    COORD : ndarray (float).
      Array with nodes coordinates.
    elements : ndarray (int)
      Array with the node number for the nodes that correspond to each
      element.
      
      
    Returns
    -------
    E_nodes : ndarray
        Strains evaluated at the nodes.
      
    
    References
    ----------
    .. [1] O.C. Zienkiewicz and J.Z. Zhu, The Superconvergent patch
        recovery and a posteriori error estimators. Part 1. The
        recovery technique, Int. J. Numer. Methods Eng., 33,
        1331-1364 (1992).
    """
    iet = elements[0, 1]
    ndof, nnodes, ngpts = fe.eletype(iet)

    elcoor = np.zeros([nnodes, 2])
    E_nodes = np.zeros([COORD.shape[0], 3])
    S_nodes = np.zeros([COORD.shape[0], 3])
    el_nodes = np.zeros([COORD.shape[0]], dtype=int)
    ul = np.zeros([ndof])
    for i in range(ne):
        young, poisson = mats[elements[i, 2], :]
        shear = young/(2*(1 + poisson))
        fact1 = young/(1 - poisson**2)
        fact2 = poisson*young/(1 - poisson**2)
        for j in range(nnodes):
            elcoor[j, 0] = COORD[IELCON[i, j], 0]
            elcoor[j, 1] = COORD[IELCON[i, j], 1]
        for j in range(ndof):
            ul[j] = UU[i, j]
        if iet == 1:
            epsG, xl = fe.str_el4(elcoor, ul)
            extrap0 = interp2d(xl[:, 0], xl[:,1], epsG[:, 0])
            extrap1 = interp2d(xl[:, 0], xl[:,1], epsG[:, 1])
            extrap2 = interp2d(xl[:, 0], xl[:,1], epsG[:, 2])
        elif iet == 2:
            epsG, xl = fe.str_el6(elcoor, ul)
            extrap0 = interp2d(xl[:, 0], xl[:,1], epsG[:, 0])
            extrap1 = interp2d(xl[:, 0], xl[:,1], epsG[:, 1])
            extrap2 = interp2d(xl[:, 0], xl[:,1], epsG[:, 2])
        elif iet == 3:
            epsG, xl = fe.str_el3(elcoor, ul)
            extrap0 = lambda x, y: epsG[0, 0]
            extrap1 = lambda x, y: epsG[0, 1]
            extrap2 = lambda x, y: epsG[0, 2]

        for node in IELCON[i, :]:
            x, y = COORD[node, :]
            E_nodes[node, 0] = E_nodes[node, 0] + extrap0(x, y)
            E_nodes[node, 1] = E_nodes[node, 1]  + extrap1(x, y)
            E_nodes[node, 2] = E_nodes[node, 2] + extrap2(x, y)
            S_nodes[node, 0] = S_nodes[node, 0] + fact1*extrap0(x, y) \
                        + fact2*extrap1(x, y)
            S_nodes[node, 1] = S_nodes[node, 1] + fact2*extrap0(x, y) \
                        + fact1*extrap1(x, y)
            S_nodes[node, 2] = S_nodes[node, 2] + shear*extrap2(x, y)
            el_nodes[node] = el_nodes[node] + 1

    E_nodes[:, 0] = E_nodes[:, 0]/el_nodes
    E_nodes[:, 1] = E_nodes[:, 1]/el_nodes
    E_nodes[:, 2] = E_nodes[:, 2]/el_nodes
    S_nodes[:, 0] = S_nodes[:, 0]/el_nodes
    S_nodes[:, 1] = S_nodes[:, 1]/el_nodes
    S_nodes[:, 2] = S_nodes[:, 2]/el_nodes
    return E_nodes, S_nodes
Exemple #4
0
def strain_nodes(nodes, elements, mats, UC):
    """Compute averaged strains and stresses at nodes

    First, the variable is extrapolated from the Gauss
    point to nodes for each element. Then, these values are averaged
    according to the number of element that share that node. The theory
    for this technique can be found in [1]_.

    Parameters
    ----------
    nodes : ndarray (float).
        Array with nodes coordinates.
    elements : ndarray (int)
        Array with the node number for the nodes that correspond
        to each element.
    mats : ndarray (float)
        Array with material profiles.
    UC : ndarray (float)
        Array with the displacements. This one contains both, the
        computed and imposed values.

    Returns
    -------
    E_nodes : ndarray
        Strains evaluated at the nodes.


    References
    ----------
    .. [1] O.C. Zienkiewicz and J.Z. Zhu, The Superconvergent patch
        recovery and a posteriori error estimators. Part 1. The
        recovery technique, Int. J. Numer. Methods Eng., 33,
        1331-1364 (1992).
    """
    ne = elements.shape[0]
    nn = nodes.shape[0]
    iet = elements[0, 1]
    ndof, nnodes, _ = fe.eletype(iet)

    elcoor = np.zeros([nnodes, 2])
    E_nodes = np.zeros([nn, 3])
    S_nodes = np.zeros([nn, 3])
    el_nodes = np.zeros([nn], dtype=int)
    ul = np.zeros([ndof])
    IELCON = elements[:, 3:]

    for i in range(ne):
        young, poisson = mats[np.int(elements[i, 2]), :]
        shear = young / (2 * (1 + poisson))
        fact1 = young / (1 - poisson**2)
        fact2 = poisson * young / (1 - poisson**2)
        for j in range(nnodes):
            elcoor[j, 0] = nodes[IELCON[i, j], 1]
            elcoor[j, 1] = nodes[IELCON[i, j], 2]
            ul[2 * j] = UC[IELCON[i, j], 0]
            ul[2 * j + 1] = UC[IELCON[i, j], 1]
        if iet == 1:
            epsG, _ = fe.str_el4(elcoor, ul)
        elif iet == 2:
            epsG, _ = fe.str_el6(elcoor, ul)
        elif iet == 3:
            epsG, _ = fe.str_el3(elcoor, ul)

        for cont, node in enumerate(IELCON[i, :]):
            E_nodes[node, 0] = E_nodes[node, 0] + epsG[cont, 0]
            E_nodes[node, 1] = E_nodes[node, 1] + epsG[cont, 1]
            E_nodes[node, 2] = E_nodes[node, 2] + epsG[cont, 2]
            S_nodes[node, 0] = S_nodes[node, 0] + fact1*epsG[cont, 0] \
                        + fact2*epsG[cont, 1]
            S_nodes[node, 1] = S_nodes[node, 1] + fact2*epsG[cont, 0] \
                        + fact1*epsG[cont, 1]
            S_nodes[node, 2] = S_nodes[node, 2] + shear * epsG[cont, 2]
            el_nodes[node] = el_nodes[node] + 1

    E_nodes[:, 0] = E_nodes[:, 0] / el_nodes
    E_nodes[:, 1] = E_nodes[:, 1] / el_nodes
    E_nodes[:, 2] = E_nodes[:, 2] / el_nodes
    S_nodes[:, 0] = S_nodes[:, 0] / el_nodes
    S_nodes[:, 1] = S_nodes[:, 1] / el_nodes
    S_nodes[:, 2] = S_nodes[:, 2] / el_nodes
    return E_nodes, S_nodes
Exemple #5
0
def strain_nodes(IELCON, UU, ne, COORD, elements, mats):
    """Compute averaged strains and stresses at nodes
    
    First, the variable is extrapolated from the Gauss
    point to nodes for each element. Then, these values are averaged
    according to the number of element that share that node. The theory
    for this technique can be found in [1]_.
    
    Parameters
    ----------
    IELCON : ndarray (int)
      Array with the nodes numbers for each element.
    UU : ndarray (float)
      Array with the displacements. This one contains both, the
      computed and imposed values.
    ne : int
      Number of elements.
    COORD : ndarray (float).
      Array with nodes coordinates.
    elements : ndarray (int)
      Array with the node number for the nodes that correspond to each
      element.
      
      
    Returns
    -------
    E_nodes : ndarray
        Strains evaluated at the nodes.
      
    
    References
    ----------
    .. [1] O.C. Zienkiewicz and J.Z. Zhu, The Superconvergent patch
        recovery and a posteriori error estimators. Part 1. The
        recovery technique, Int. J. Numer. Methods Eng., 33,
        1331-1364 (1992).
    """
    iet = elements[0, 1]
    ndof, nnodes, ngpts = fe.eletype(iet)

    elcoor = np.zeros([nnodes, 2])
    E_nodes = np.zeros([COORD.shape[0], 3])
    S_nodes = np.zeros([COORD.shape[0], 3])
    el_nodes = np.zeros([COORD.shape[0]], dtype=int)
    ul = np.zeros([ndof])
    for i in range(ne):
        young, poisson = mats[elements[i, 2], :]
        shear = young / (2 * (1 + poisson))
        fact1 = young / (1 - poisson**2)
        fact2 = poisson * young / (1 - poisson**2)
        for j in range(nnodes):
            elcoor[j, 0] = COORD[IELCON[i, j], 0]
            elcoor[j, 1] = COORD[IELCON[i, j], 1]
        for j in range(ndof):
            ul[j] = UU[i, j]
        if iet == 1:
            epsG, xl = fe.str_el4(elcoor, ul)
            extrap0 = interp2d(xl[:, 0], xl[:, 1], epsG[:, 0])
            extrap1 = interp2d(xl[:, 0], xl[:, 1], epsG[:, 1])
            extrap2 = interp2d(xl[:, 0], xl[:, 1], epsG[:, 2])
        elif iet == 2:
            epsG, xl = fe.str_el6(elcoor, ul)
            extrap0 = interp2d(xl[:, 0], xl[:, 1], epsG[:, 0])
            extrap1 = interp2d(xl[:, 0], xl[:, 1], epsG[:, 1])
            extrap2 = interp2d(xl[:, 0], xl[:, 1], epsG[:, 2])
        elif iet == 3:
            epsG, xl = fe.str_el3(elcoor, ul)
            extrap0 = lambda x, y: epsG[0, 0]
            extrap1 = lambda x, y: epsG[0, 1]
            extrap2 = lambda x, y: epsG[0, 2]

        for node in IELCON[i, :]:
            x, y = COORD[node, :]
            E_nodes[node, 0] = E_nodes[node, 0] + extrap0(x, y)
            E_nodes[node, 1] = E_nodes[node, 1] + extrap1(x, y)
            E_nodes[node, 2] = E_nodes[node, 2] + extrap2(x, y)
            S_nodes[node, 0] = S_nodes[node, 0] + fact1*extrap0(x, y) \
                        + fact2*extrap1(x, y)
            S_nodes[node, 1] = S_nodes[node, 1] + fact2*extrap0(x, y) \
                        + fact1*extrap1(x, y)
            S_nodes[node, 2] = S_nodes[node, 2] + shear * extrap2(x, y)
            el_nodes[node] = el_nodes[node] + 1

    E_nodes[:, 0] = E_nodes[:, 0] / el_nodes
    E_nodes[:, 1] = E_nodes[:, 1] / el_nodes
    E_nodes[:, 2] = E_nodes[:, 2] / el_nodes
    S_nodes[:, 0] = S_nodes[:, 0] / el_nodes
    S_nodes[:, 1] = S_nodes[:, 1] / el_nodes
    S_nodes[:, 2] = S_nodes[:, 2] / el_nodes
    return E_nodes, S_nodes