def scatter(DME, UG, ne, neq, elements):
    """Scatter the nodal displacements vector `UG` over each element

    Parameters
    ----------
    DME : ndarray (int)
      Array that shows the connectivity of degrees of freedom.
    UG : ndarray (float)
      Array with the computed displacements.
    ne : int
      Number of elements.
    neq : int
      Number of equations (degrees of freedom).
    elements : ndarray (int)
      Array with the node number for the nodes that correspond to each
      element.

    Returns
    -------
    UU : ndarray (float)
      Array with the displacements. This one contains both, the
      computed and imposed values.

    """
    iet = elements[0, 1]
    ndof, nnodes, ngpts = fe.eletype(iet)
    UU = np.zeros([ne, ndof], dtype=np.float)
    for i in range(ne):
        for ii in range(ndof):
            kk = DME[i, ii]
            if kk != -1:
                UU[i, ii] = UG[kk]

    return UU
Exemple #2
0
def eleDisp(Up, iet, dme, i):
    """
    This function find displacements of element i. Returns 1D array
    with x, y and rotation displacements values in each node. 
    
    Parameters
    ----------
    Up     : Displacement al time t + dtaT (not converged).
    iet    : Element i type
    dme    : Assembly operator that indicates degrees of freedom correspondence of the element.
    i      : Element indicator 
    
    """
    ndof, nnodes, ngpts = fem.eletype(iet)
    ele_disp = np.zeros((ndof,))
    #
    for j in range (ndof):
         ID_dof = dme[j]
         if ID_dof == -1:
              ele_disp[j] = 0.0
         else:
              ele_disp[j] = Up[ID_dof]
         # End if
    #End for
    return ele_disp
def scatter(DME, UG, ne, neq, elements):
    """Scatter the nodal displacements vector `UG` over each element

    Parameters
    ----------
    DME : ndarray (int)
      Array that shows the connectivity of degrees of freedom.
    UG : ndarray (float)
      Array with the computed displacements.
    ne : int
      Number of elements.
    neq : int
      Number of equations (degrees of freedom).
    elements : ndarray (int)
      Array with the node number for the nodes that correspond to each
      element.

    Returns
    -------
    UU : ndarray (float)
      Array with the displacements. This one contains both, the
      computed and imposed values.

    """
    iet = elements[0, 1]
    ndof, nnodes, ngpts = fe.eletype(iet)
    UU = np.zeros([ne, ndof], dtype=np.float)
    for i in range(ne):
        for ii in range(ndof):
            kk = DME[i, ii]
            if kk != -1:
                UU[i, ii] = UG[kk]

    return UU
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
Exemple #6
0
def retriever(elements , mats , nodes , i, uel=None):
    """Computes the elemental stiffness matrix of element i

    Parameters
    ----------
    elements : ndarray
      Array with the number for the nodes in each element.
    mats    : ndarray.
      Array with the material profiles.
    nodes    : ndarray.
      Array with the nodal numbers and coordinates.
    i    : int.
      Identifier of the element to be assembled.

    Returns
    -------
    kloc : ndarray (float)
      Array with the local stiffness matrix.
    ndof : int.
      Number of degrees of fredom of the current element.
    """
    IELCON = np.zeros([9], dtype=np.integer)
    iet = elements[i, 1]
    ndof, nnodes, ngpts = fem.eletype(iet)
    elcoor = np.zeros([nnodes, 2])
    im = np.int(elements[i, 2])
    par0, par1 = mats[im, :]
    for j in range(nnodes):
        IELCON[j] = elements[i, j+3]
        elcoor[j, 0] = nodes[IELCON[j], 1]
        elcoor[j, 1] = nodes[IELCON[j], 2]
    if uel is None:
        if iet == 1:
            kloc = ue.uel4nquad(elcoor, par1, par0)
        elif iet == 2:
            kloc = ue.uel6ntrian(elcoor, par1, par0)
        elif iet == 3:
            kloc = ue.uel3ntrian(elcoor, par1, par0)
        elif iet == 5:
            kloc = ue.uelspring(elcoor, par1, par0)
        elif iet == 6:
            kloc = ue.ueltruss2D(elcoor, par1, par0)
        elif iet == 7:
            kloc = ue.uelbeam2DU(elcoor, par1, par0)
    else:
        kloc, ndof, iet = uel(elcoor, par1, par0)

    return kloc, ndof, iet
Exemple #7
0
def DME(nodes, elements):
    """Counts active equations, creates BCs array IBC[]
    and the assembly operator DME[]

    Parameters
    ----------
    nodes    : ndarray.
      Array with the nodal numbers and coordinates.
    elements : ndarray
      Array with the number for the nodes in each element.

    Returns
    -------
    DME : ndarray (int)
      Assembly operator.
    IBC : ndarray (int)
      Boundary conditions array.
    neq : int
      Number of active equations in the system.

    """
    nels = elements.shape[0]
    IELCON = np.zeros([nels, 9], dtype=np.integer)
    DME = np.zeros([nels, 18], dtype=np.integer)

    neq, IBC = eqcounter(nodes)

    for i in range(nels):
        iet = elements[i, 1]
        ndof, nnodes, ngpts = fem.eletype(iet)
        for j in range(nnodes):
            IELCON[i, j] = elements[i, j+3]
            kk = IELCON[i, j]
            for l in range(2):
                DME[i, 2*j+l] = IBC[kk, l]

    return DME , IBC , neq
Exemple #8
0
def DME(IBC, ne, elements):
    """Create the assembly operator

    Create the assembly operator DME and processes the element
    connectivity array IELCON

    Parameters
    ----------
    IBC : ndarray
      Array that maps the nodes with number of equations.
    ne : int
      Number of elements.
    elements : ndarray
      Array with the number for the nodes in each element.

    Returns
    -------
    DME : ndarray (int)
      Assembly operator.
    IELCON : ndarray (int)
      Element connectivity.

    """
    IELCON = np.zeros([ne, 9], dtype=np.integer)
    DME = np.zeros([ne, 18], dtype=np.integer)

    for i in range(ne):
        iet = elements[i, 1]
        ndof, nnodes, ngpts = fem.eletype(iet)
        for j in range(nnodes):
            IELCON[i, j] = elements[i, j + 3]
            kk = IELCON[i, j]
            for l in range(2):
                DME[i, 2 * j + l] = IBC[kk, l]

    return DME, IELCON
Exemple #9
0
def DME(IBC, ne, elements):
    """Create the assembly operator

    Create the assembly operator DME and processes the element
    connectivity array IELCON

    Parameters
    ----------
    IBC : ndarray
      Array that maps the nodes with number of equations.
    ne : int
      Number of elements.
    elements : ndarray
      Array with the number for the nodes in each element.

    Returns
    -------
    DME : ndarray (int)
      Assembly operator.
    IELCON : ndarray (int)
      Element connectivity.

    """
    IELCON = np.zeros([ne, 9], dtype=np.integer)
    DME = np.zeros([ne, 18], dtype=np.integer)

    for i in range(ne):
        iet = elements[i, 1]
        ndof, nnodes, ngpts = fem.eletype(iet)
        for j in range(nnodes):
            IELCON[i, j] = elements[i, j+3]
            kk = IELCON[i, j]
            for l in range(2):
                DME[i, 2*j+l] = IBC[kk, l]

    return DME, IELCON
Exemple #10
0
def readin(folder):
    """Read the input files"""
    inipar        = np.loadtxt(folder + '01_Inipar.txt', ndmin=2, usecols=(0), skiprows=6)
    nodes         = np.loadtxt(folder + '03_Nodes.txt' , ndmin=2, skiprows=3)
    loads         = np.loadtxt(folder + '05_Nodal_loads.txt' , ndmin=2, skiprows=3)
    #
    # -------------------------------------------------------------------------------------
    # Read constraints file and identify if there is any diaphfragm or constraint
    const         = np.loadtxt(folder + '07_DOF_Constraints.txt' , ndmin=2, skiprows=9)
    DPH_flag = 0
    CST_flag = 0
    #
    if len(const) != 0:
       if max(const[:,1]) >= 0:
           DPH_flag = 1
       if min(const[:,1]) < 0:
           CST_flag = 1
       # End if
    #End if   
    const = list(const)
    const.insert(0,CST_flag)
    const.insert(0,DPH_flag)
    #
    # -------------------------------------------------------------------------------------
    #
    NLSTA  = int(inipar[5,0])
    NLDYNA = int(inipar[6,0])
    #
    if (NLSTA == 1) and (NLDYNA == 0):
       Seismo_signal = []
    elif (NLSTA == 0) and (NLDYNA == 1):
       Seismo_signal = np.loadtxt(folder + '06_Seismo_signal.txt' , skiprows=5)
    elif (NLSTA == 1) and (NLDYNA == 1):
       Seismo_signal = np.loadtxt(folder + '06_Seismo_signal.txt' , skiprows=5)
    # End if
    #
    # -------------------------------------------------------------------------------------   
    # Read material - parameters file
    mat_file = open(folder + '02_Mater.txt', 'r')
    #
    mats    = []
    matflag = 0
    for line in mat_file:
         if matflag == 1:
              l = np.array(line.split(), dtype = float)
              mats.append(l)
         # End if
         if line == 'PARAMETERS INFORMATION\n':
            matflag = 1
         #End if
    #End for
    #
    # -------------------------------------------------------------------------------------        
    # Read elements file
    eles_file = open(folder + '04_Eles.txt', 'r')
    #
    elements = []
    eleflag  = 0
    for line in eles_file:
         if eleflag == 1:
              l = np.array(line.split(), dtype = int)
              elements.append(l)
         #End if
         if line == 'ELEMENTS\n':
            eleflag = 1
         #End if
    #End for
    #
    # -------------------------------------------------------------------------------------        
    # Initialize Msvar (List where state variables of each element will be stocked)
    Msvar = []
    ILF   = []
    nele  = len(elements)
    #
    for i in range (nele):
       #
       iet = elements[i][1]
       ndof, nnodes, ngpts = fem.eletype(iet)
       #
       if iet == 0: # Linear - 1D Spring
          nsvar = 1
       if iet == 1: # Linear - Simple frame
          nsvar = 1
       if iet == 2: # Linear - Full frame
          nsvar = 1
       if iet == 3: # Linear - 2D Truss
          nsvar = 1
       if iet == 4: # NonLin - 4 noded plate (Rutinas de Jefe)
          nsvar = 88
       if iet == 5: # NonLin - 1D Spring
          nsvar = 5
       if iet == 6: # Lin - 2D shear-rotational Spring
          nsvar = 1
       if iet == 7: # Lin - 1D rotational Spring
          nsvar = 1 
       if iet == 8: # NonLin - 1D rotational Spring
          nsvar = 5 
       if iet == 9: # NonLin - 1D pile spring for stiff soils
          nsvar = 4
       if iet == 10: # Linear - 3D full frame bending ans shear effects
          nsvar = 1    
       # End if
       #
       ele_svar = np.zeros((nsvar))
       ele_ilf  = np.zeros((ndof))
       Msvar.append(ele_svar)
       ILF.append(ele_ilf)
    # End for
    # -------------------------------------------------------------------------------------   
    return inipar, nodes, mats, elements, loads, Msvar, ILF, Seismo_signal, const
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 #12
0
def matassem(IBC, mats, elements, nn, ne, neq, COORD, DME, IELCON):
    """Assembles the global stiffness matrix KG

    Parameters
    ----------
    IBC : ndarray (int)
      Array that maps the nodes with number of equations.
    mats : ndarray
      Material properties.
    elements : ndarray
      Array with the number for the nodes in each element.
    nn : int
      Number of nodes.
    ne : int
      Number of elements.
    neq : int
      Number of equations in the system after removing the nodes
      with imposed displacements.
    COORD : ndarray
      Coordinates of the nodes.
    DME : ndarray (int)
      Assembly operator.
    IELCON : ndarray (int)
      Element connectivity.

    Returns
    -------
    KG : ndarray
      Global stiffness matrix.

    """
    KG = np.zeros([neq, neq])
    for i in range(ne):
        iet = elements[i, 1]
        ndof, nnodes, ngpts = fem.eletype(iet)
        elcoor = np.zeros([nnodes, 2])
        kloc = np.zeros([ndof, ndof])
        im = elements[i, 2]
        emod = mats[im, 0]
        enu = mats[im, 1]
        dme = np.zeros([ndof], dtype=np.integer)
        for j in range(nnodes):
            elcoor[j, 0] = COORD[IELCON[i, j], 0]
            elcoor[j, 1] = COORD[IELCON[i, j], 1]
        if iet == 1:
            kloc = ue.uel4nquad(elcoor, enu, emod)
        elif iet == 2:
            kloc = ue.uel6ntrian(elcoor, enu, emod)
        elif iet == 3:
            kloc = ue.uel3ntrian(elcoor, enu, emod)
        for ii in range(ndof):
            dme[ii] = DME[i, ii]
        for ii in range(ndof):
            kk = dme[ii]
            if kk != -1:
                for jj in range(ndof):
                    ll = dme[jj]
                    if ll != -1:
                        KG[kk, ll] = KG[kk, ll] + kloc[ii, jj]

    return KG
Exemple #13
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 #14
0
def retriever(Up, svar, dme, ac, elements , mats , nodes , i, uel=None):
    """Computes the elemental stiffness matrix of element i

    Parameters
    ----------
    Up       : ndarray
               Array with the nodal displacement at time t
    svar     : python list
               List with the state variables of the element of the last converged increment.
    dme      : ndarray (int)
               Assembly operator that indicates degrees of freedom correspondence of the element.
    ac       : 1D array
               Integration constants
    elements : ndarray
               Array with the number for the nodes in each element.
    mats     : ndarray.
               Array with the material profiles.
    nodes    : ndarray.
               Array with the nodal numbers and coordinates.
    i        : int.
               Identifier of the element to be assembled.

    Returns
    -------
    kloc : ndarray (float)
           Array with the local stiffness matrix.
    mloc : ndarray (float)
           Array with the local mass matrix.
    cloc : ndarray (float)
           Array with the local damping matrix.
    svar : Python list
           List with the state variables of the current element.
    ndof : int.
           Number of degrees of freedom of the current element.           
    """
    #
    iet    = elements[i][1]
    #
    ndof, nnodes, ngpts = fem.eletype(iet)
    iele_disp = eleDisp(Up, iet, dme, i)
    #
    elcoor = np.zeros([nnodes, 3])
    im     = np.int(elements[i][2])
    par    = mats[im]
    
    for j in range(nnodes):
        IELCON       = elements[i][j+3]  # Index of each node of the element
        elcoor[j, 0] = nodes[IELCON, 1]  # X coordinate of the node
        elcoor[j, 1] = nodes[IELCON, 2]  # X coordinate of the node
        elcoor[j, 2] = nodes[IELCON, 3]  # X coordinate of the node
    # End for j
    #
    if uel is None:
        if   iet == 0:
             kloc , mloc , cloc , svar, ilf = ue.L_1Dspring(iele_disp, elcoor, par, svar)
        if   iet == 1:
             kloc , mloc , cloc , svar, ilf = ue.L_sframe(iele_disp, elcoor, par, svar)
        elif iet == 2:
             kloc , mloc , cloc , svar, ilf = ue.L_fframe(iele_disp, elcoor, par, svar)
        elif iet == 3:
             kloc , mloc , cloc , svar, ilf = ue.L_2Dtruss(iele_disp, elcoor, par, svar)
        elif iet == 4: 
             kloc , mloc , cloc , svar, ilf = slds.uel4nquad_PLK(elcoor, par, svar, iele_disp)
        elif iet == 5: 
             kloc , mloc , cloc , svar, ilf = ue.NL_1Dspring(iele_disp, elcoor, par, svar)
        elif iet == 6: 
             kloc , mloc , cloc , svar, ilf = ue.L_2DRotspg(iele_disp, elcoor, par, svar)
        elif iet == 7: 
             kloc , mloc , cloc , svar, ilf = ue.L_1DRotspg(iele_disp, elcoor, par, svar)
        elif iet == 8: 
             kloc , mloc , cloc , svar, ilf = ue.NL_1DRotspg(iele_disp, elcoor, par, svar)
        elif iet == 9: 
             kloc , mloc , cloc , svar, ilf = ue.NL_1DPileRCK(iele_disp, elcoor, par, svar) 
        elif iet == 10:
             kloc , mloc , cloc , svar, ilf = ue.L_3Dfframe(iele_disp, elcoor, par, svar)     
    else:
        kloc, ndof, iet = uel(elcoor, par)
    
    return kloc, mloc, cloc, svar, ndof, ilf
Exemple #15
0
def DME(nodes, elements):
    """Counts active equations, creates BCs array IBC[]
    and the assembly operator DME[]

    Parameters
    ----------
    nodes    : ndarray.
      Array with the nodal numbers and coordinates.
    elements : ndarray
      Array with the number for the nodes in each element.
    iet :  int (This is not an input for this function)
      Type of element. These are:
        0.  Linear - 1D Spring in X direction.   
        1.  Linear - Simple frame.
        2.  Linear - Full frame.
        3.  Linear - 2D Truss.
        4.  NonLin - 4 noded plate.
        5.  NonLin - 1D Spring in X direction.
        6.  Linear - 2D Shear-Rotational spring.
        7.  Linear - 1D Rotational spring.
        8.  NonLin - 1D Rotational spring.
        9.  NonLin - 1D pile spring P-Y curve for stiff soil
        10. Linear - 3D full frame bending and shear effects

    Returns
    -------
    DME : ndarray (int)
      Assembly operator.
    IBC : ndarray (int)
      Boundary conditions array.
    neq : int
      Number of active equations in the system.

    """
    nels = len(elements)
    IELCON = np.zeros([nels, 4], dtype=np.integer) # 4 por que es el máximo numero de nodos que conforman un elemento
    DME = []
    
    neq, IBC = eqcounter(nodes)

    for i in range(nels):
        dme = []
        iet = elements[i][1]
        ndof, nnodes, ngpts = fem.eletype(iet)
        for j in range(nnodes):
            IELCON[i, j] = elements[i][j+3]
            kk = IELCON[i, j]
            #
            if iet == 0:
               dme.append(IBC[kk, 0])
            elif iet == 1:
               dme.append(IBC[kk, 0])
               dme.append(IBC[kk, 1])
               dme.append(IBC[kk, 5])
            elif iet == 2:
               dme.append(IBC[kk, 0])
               dme.append(IBC[kk, 1])
               dme.append(IBC[kk, 5])
            elif iet == 3:
               dme.append(IBC[kk, 0])
               dme.append(IBC[kk, 1])
            elif iet == 4:
               dme.append(IBC[kk, 0])
               dme.append(IBC[kk, 1]) 
            elif iet == 5:
               dme.append(IBC[kk, 0])
            elif iet == 6:
               dme.append(IBC[kk, 1])
               dme.append(IBC[kk, 5])
            elif iet == 7:
               dme.append(IBC[kk, 5])
            elif iet == 8:
               dme.append(IBC[kk, 5])
            elif iet == 9:
               dme.append(IBC[kk, 0])
            elif iet == 10:
               dme.append(IBC[kk, 0])
               dme.append(IBC[kk, 1]) 
               dme.append(IBC[kk, 2]) 
               dme.append(IBC[kk, 3]) 
               dme.append(IBC[kk, 4]) 
               dme.append(IBC[kk, 5]) 
            #End if
        # End for j
        DME.append(dme)
    # ENd for i
    return DME, IBC, neq
Exemple #16
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
Exemple #17
0
def matassem(IBC, mats, elements, nn, ne, neq, COORD, DME, IELCON):
    """Assembles the global stiffness matrix KG

    Parameters
    ----------
    IBC : ndarray (int)
      Array that maps the nodes with number of equations.
    mats : ndarray
      Material properties.
    elements : ndarray
      Array with the number for the nodes in each element.
    nn : int
      Number of nodes.
    ne : int
      Number of elements.
    neq : int
      Number of equations in the system after removing the nodes
      with imposed displacements.
    COORD : ndarray
      Coordinates of the nodes.
    DME : ndarray (int)
      Assembly operator.
    IELCON : ndarray (int)
      Element connectivity.

    Returns
    -------
    KG : ndarray
      Global stiffness matrix.

    """
    KG = np.zeros([neq, neq])
    for i in range(ne):
        iet = elements[i, 1]
        ndof, nnodes, ngpts = fem.eletype(iet)
        elcoor = np.zeros([nnodes, 2])
        kloc = np.zeros([ndof, ndof])
        im = elements[i, 2]
        emod = mats[im, 0]
        enu = mats[im, 1]
        dme = np.zeros([ndof], dtype=np.integer)
        for j in range(nnodes):
            elcoor[j, 0] = COORD[IELCON[i, j], 0]
            elcoor[j, 1] = COORD[IELCON[i, j], 1]
        if iet == 1:
            kloc = ue.uel4nquad(elcoor, enu, emod)
        elif iet == 2:
            kloc = ue.uel6ntrian(elcoor, enu, emod)
        elif iet == 3:
            kloc = ue.uel3ntrian(elcoor, enu, emod)
        for ii in range(ndof):
            dme[ii] = DME[i, ii]
        for ii in range(ndof):
            kk = dme[ii]
            if kk != -1:
                for jj in range(ndof):
                    ll = dme[jj]
                    if ll != -1:
                        KG[kk, ll] = KG[kk, ll] + kloc[ii, jj]

    return KG