Пример #1
0
def addFaceTraction(order, assembler, load):
    # Create the surface traction
    aux = TACS.AuxElements()

    # Get the element node locations
    nelems = assembler.getNumElements()
    for i in range(nelems):
        # Get the information about the given element
        elem, Xpt, vars0, dvars, ddvars = assembler.getElementData(i)

        # Loop over the nodes and create the traction forces in the
        # x/y/z directions
        nnodes = order*order
        tx = np.zeros(nnodes, dtype=TACS.dtype)
        ty = np.zeros(nnodes, dtype=TACS.dtype)
        tz = np.zeros(nnodes, dtype=TACS.dtype)

        # Set the components of the surface traction
        for j in range(nnodes):
            x = Xpt[3*j]
            y = Xpt[3*j+1]
            z = Xpt[3*j+2]
            theta = -R*np.arctan2(y, x)
            p = -load*np.sin(beta*z)*np.sin(alpha*theta)

            tx[j] = p*Xpt[3*j]/R
            ty[j] = p*Xpt[3*j+1]/R
            tz[j] = 0.0

        trac = elements.ShellTraction(order, tx, ty, tz)
        aux.addElement(i, trac)
        
    return aux
Пример #2
0
 def createAuxElements(self, assembler, order=3):
     aux = TACS.AuxElements()
     tx = np.zeros(order * order)
     ty = np.zeros(order * order)
     tz = -np.ones(order * order)
     trac = elements.ShellTraction(order, tx, ty, tz)
     for i in range(assembler.getNumElements()):
         aux.addElement(i, trac)
     return aux
Пример #3
0
def computeTractionLoad(name, forest, assembler, trac):
    """
    Add a surface traction to all quadrants or octants that touch a face or edge with
    the given name. The assembler must be created from the provided forest. The list
    trac must have a traction for each face (6) for octants or each edge (4) for
    quadrants.

    Note: This code uses the fact that the getOctsWithName or getQuadsWithName returns
    the local face or edge index touching the surface or edge in the info member.

    Args:
        name (str): Name of the surface where the traction will be added
        forest (QuadForest or OctForest): Forest for the finite-element mesh
        assembler (Assembler): TACSAssembler object for the finite-element problem
        trac (list): List of tractions, one for each possible face/edge orientation

    Returns:
        Vec: A force vector containing the traction
    """

    if isinstance(forest, TMR.OctForest):
        octants = forest.getOctants()
        face_octs = forest.getOctsWithName(name)
    elif isinstance(forest, TMR.QuadForest):
        octants = forest.getQuadrants()
        face_octs = forest.getQuadsWithName(name)

    # Create the force vector and zero the variables in the assembler
    force = assembler.createVec()
    assembler.zeroVariables()

    # Create the auxiliary element class
    aux = TACS.AuxElements()

    for i in range(len(face_octs)):
        index = face_octs[i].tag
        if index is not None:
            aux.addElement(index, trac[face_octs[i].info])

    # Keep auxiliary elements already set in the assembler
    # aux_tmp = assembler.getAuxElements()
    assembler.setAuxElements(aux)

    # Compute the residual where force = -residual
    assembler.assembleRes(force)
    force.scale(-1.0)

    # Reset the auxiliary elements
    assembler.setAuxElements(None)  # (aux_tmp)

    return force
Пример #4
0
def addFaceTraction(order, forest, attr, assembler, tr):
    trac = []
    for findex in range(6):
        trac.append(elements.Traction3D(order, findex, tr[0], tr[1], tr[2]))

    # Retrieve octants from the forest
    octants = forest.getOctants()
    face_octs = forest.getOctsWithAttribute(attr)
    aux = TACS.AuxElements()

    for i in range(len(face_octs)):
        aux.addElement(face_octs[i].tag, trac[face_octs[i].info])

    return aux
Пример #5
0
def rectangular_domain(nx, ny, Ly=100.0):

    # Set the y-dimension based on a unit aspect ratio
    Lx = (nx*Ly)/ny

    # Compute the total area
    area = Lx*Ly
    
    # Set the number of elements/nodes in the problem
    nnodes = (nx+1)*(ny+1)
    nelems = nx*ny
    nodes = np.arange(nnodes).reshape((nx+1, ny+1))          

    # Set the node locations
    xpts = np.zeros((nnodes, 3))
    x = np.linspace(0, Lx, nx+1)
    y = np.linspace(0, Ly, ny+1)
    for j in range(ny+1):
        for i in range(nx+1):
            xpts[nodes[i,j],0] = x[i]
            xpts[nodes[i,j],1] = y[j]

    # Set the connectivity and create the corresponding elements
    conn = np.zeros((nelems, 4), dtype=np.intc)
    for j in range(ny):
        for i in range(nx):
            # Append the first set of nodes
            n = i + nx*j
            conn[n,0] = nodes[i, j]
            conn[n,1] = nodes[i+1, j]
            conn[n,2] = nodes[i, j+1]
            conn[n,3] = nodes[i+1, j+1]

    bcs = np.array(nodes[0,:], dtype=np.intc)
            
    # Create the tractions and add them to the surface
    surf = 1 # The u=1 positive surface
    tx = np.zeros(2)
    ty = -100*np.ones(2)
    trac = elements.PSQuadTraction(surf, tx, ty)

    # Create the auxiliary element class    
    aux = TACS.AuxElements()
    for j in range(int(ny/8)):
        num = nx-1 + nx*j
        aux.addElement(num, trac)
        
    return xpts, conn, bcs, aux, area
Пример #6
0
def addEdgeTraction(order, forest, attr, assembler, tr):
    trac = []

    for findex in range(4):
        trac.append(elements.PSQuadTraction(findex, tr[0]*np.ones(2), \
                                            tr[1]*np.ones(2)))

    # Retrieve octants from the forest
    quadrants = forest.getQuadrants()
    edge_quads = forest.getQuadsWithAttribute(attr)
    aux = TACS.AuxElements()

    for i in range(len(edge_quads)):
        index = quadrants.findIndex(edge_quads[i])
        if index is not None:
            aux.addElement(index, trac[edge_quads[i].tag])

    return aux
Пример #7
0
def addFaceTraction(order, forest, assembler):
    # Get the quadrilaterals of interest
    quads = forest.getQuadsWithName('traction')

    # Create the surface traction
    aux = TACS.AuxElements()

    # Loop over the nodes and create the traction forces in the x/y/z
    # directions
    nnodes = order
    tx = np.zeros(nnodes, dtype=TACS.dtype)
    ty = np.zeros(nnodes, dtype=TACS.dtype)
    ty[:] = 10.0

    # Create the shell traction
    surf = 1
    trac = elements.PSQuadTraction(surf, tx, ty)
    for q in quads:
        aux.addElement(q.tag, trac)

    return aux
Пример #8
0
Файл: crm.py Проект: xyuan/tmr
def addFaceTraction(order, assembler):
    # Create the surface traction
    aux = TACS.AuxElements()

    # Get the element node locations
    nelems = assembler.getNumElements()

    # Loop over the nodes and create the traction forces in the x/y/z
    # directions
    nnodes = order * order
    tx = np.zeros(nnodes, dtype=TACS.dtype)
    ty = np.zeros(nnodes, dtype=TACS.dtype)
    tz = np.zeros(nnodes, dtype=TACS.dtype)
    tz[:] = 5.0

    # Create the shell traction
    trac = elements.ShellTraction(order, tx, ty, tz)
    for i in range(nelems):
        aux.addElement(i, trac)

    return aux
Пример #9
0
def createAssembler(m=5.0, c=0.5, k=5.0, u0=-0.5, udot0=1.0, pc=None):
    num_disps = 1
    num_nodes = 1

    # Spring element
    #spr = SpringMassDamper(num_disps, num_nodes, m, c, k)
    dspr = PSPACE.PySMD(m, c, k, u0, udot0)
    sprcb = SMDUpdate(dspr)
    sspr = PSPACE.PyStochasticElement(dspr, pc, sprcb)

    dforce = ForcingElement(num_disps, num_nodes, amplitude=1.0, omega=10.0)
    forcecb = ForceUpdate(dforce)
    sforce = PSPACE.PyStochasticElement(dforce, pc, forcecb)

    ndof_per_node = 1 * pc.getNumBasisTerms()
    num_owned_nodes = 1
    num_elems = 1

    # Add user-defined element to TACS
    comm = MPI.COMM_WORLD
    assembler = TACS.Assembler.create(comm, ndof_per_node, num_owned_nodes,
                                      num_elems)

    ptr = np.array([0, 1], dtype=np.intc)
    conn = np.array([0], dtype=np.intc)
    assembler.setElementConnectivity(ptr, conn)

    # Set elements
    assembler.setElements([sspr])

    # set Auxiliary elements
    aux = TACS.AuxElements()
    aux.addElement(0, sforce)
    assembler.setAuxElements(aux)

    assembler.initialize()

    return assembler
Пример #10
0
        elem = elements.MITCShell(order, stiff)
        return elem


def cylinderEvalTraction(Xp):
    x = Xp[0]
    y = Xp[1]
    z = Xp[2]
    theta = -R * np.arctan2(y, x)
    p = -load * np.sin(beta * z) * np.sin(alpha * theta)
    return [p * x / R, p * y / R, 0.0]


def addFaceTraction(case, order, assembler, load):
    # Create the surface traction
    aux = TACS.AuxElements()

    # Get the element node locations
    nelems = assembler.getNumElements()

    if case == 'cylinder':
        trac = elements.ShellTraction(order, evalf=cylinderEvalTraction)
        for i in range(nelems):
            aux.addElement(i, trac)

    elif case == 'disk':
        nnodes = order * order
        tx = np.zeros(nnodes, dtype=TACS.dtype)
        ty = np.zeros(nnodes, dtype=TACS.dtype)
        tz = np.zeros(nnodes, dtype=TACS.dtype)
        tz[:] = load
Пример #11
0
def bracket_domain(nb, nc, Lx=100.0):
    # Compute the total area
    area = 0.64 * Lx**2

    # The total number of elements along one direction
    nx = nb + nc

    # Allocate all of the nodes (including blanked nodes)
    nodes = np.ones((nx + 1, nx + 1), dtype=np.int)
    nodes[nb + 1:, nb + 1:] = -1

    # Allocate all of the elements (including blanked elements)
    elems = np.ones((nx, nx), dtype=np.int)
    elems[nb:, nb:] = -1

    # Number the nodes
    index = 0
    for j in range(nx + 1):
        for i in range(nx + 1):
            if nodes[i, j] >= 0:
                nodes[i, j] = index
                index += 1

    # Set the element numbering
    index = 0
    for j in range(nx):
        for i in range(nx):
            if elems[i, j] >= 0:
                elems[i, j] = index
                index += 1

    # Set the boundary conditions
    bcs = np.array(nodes[:(nb + 1), -1], dtype=np.intc)

    # Compute the number of nodes and elements
    n = (nb + 1)**2 + 2 * (nb + 1) * nc
    ne = nb**2 + 2 * nb * nc

    # Allocate the arrays
    conn = np.zeros((ne, 4), dtype=np.intc)
    xpts = np.zeros((n, 3))

    # Set the node locations
    for j in range(nx + 1):
        for i in range(nx + 1):
            if nodes[i, j] >= 0:
                xpts[nodes[i, j], 0] = (Lx * i) / nx
                xpts[nodes[i, j], 1] = (Lx * j) / nx

    # Set the nodal connectivity
    for j in range(nx):
        for i in range(nx):
            if elems[i, j] >= 0:
                conn[elems[i, j], 0] = nodes[i, j]
                conn[elems[i, j], 1] = nodes[i + 1, j]
                conn[elems[i, j], 2] = nodes[i, j + 1]
                conn[elems[i, j], 3] = nodes[i + 1, j + 1]

    # Create the tractions and add them to the surface
    surf = 1  # The u=1 positive surface
    tx = np.zeros(2)
    ty = 100 * np.ones(2)
    trac = elements.PSQuadTraction(surf, tx, ty)

    # Create the auxiliary element class
    aux = TACS.AuxElements()
    for j in range(int(5 * nb / 6), nb):
        aux.addElement(elems[-1, j], trac)

    return xpts, conn, bcs, aux, area
Пример #12
0
def createAssembler(tacs_comm):
    # Set constitutive properties
    rho = 4540.0  # density, kg/m^3
    E = 118e9  # elastic modulus, Pa 118e9
    nu = 0.325  # poisson's ratio
    ys = 1050e6  # yield stress, Pa
    kappa = 6.89
    specific_heat = 463.0

    # Set the back-pressure for the traction load
    pb = 654.9  #10.0 # A value for the surface pressure

    # Load in the mesh
    mesh = TACS.MeshLoader(tacs_comm)
    mesh.scanBDFFile('tacs_aero.bdf')

    # Get the number of components set in the mesh. Each component is
    num_components = mesh.getNumComponents()

    # Each domain consists of the union of two components. The component
    # corresponding to the surface traction and the component corresponding
    # to remaining plate elements. There is one design variable associated
    # with each domain that shares a common (x,z) coordinate
    num_domains = num_components // 2

    # Create the constitutvie propertes and model
    props_plate = constitutive.MaterialProperties(rho=rho,
                                                  specific_heat=specific_heat,
                                                  kappp=kappa,
                                                  E=E,
                                                  nu=nu,
                                                  ys=ys)

    # Create the basis class
    basis = elements.LinearHexaBasis()

    element_list = []
    for k in range(num_domains):
        # Create the elements in an element list
        con = constitutive.SolidConstitutive(props_plate, t=1.0, tNum=k)
        phys_model = elements.LinearThermoelasticity3D(con)

        # Create the element
        element_list.append(elements.Element3D(phys_model, basis))
        varsPerNode = phys_model.getVarsPerNode()

    # Set the face index for the side of the element where the traction
    # will be applied. The face indices are as follows for the hexahedral
    # basis class:
    # -x: 0, +x: 1, -y: 2, +y: 3, -z: 4, +z: 5
    faceIndex = 4

    # Set the wedge angle - 5 degrees
    theta = np.radians(5.0)

    # Compute the outward normal components for the face
    nx = np.sin(theta)
    nz = -np.cos(theta)

    # Set the traction components
    tr = [-pb * nx, 0.0, -pb * nz, 0.0]

    # Create the traction class
    traction = elements.Traction3D(varsPerNode, faceIndex, basis, tr)

    # Set the elements corresponding to each component number
    num_components = mesh.getNumComponents()
    for k in range(num_components):
        mesh.setElement(k, element_list[k % num_domains])

    # Create the assembler object
    assembler = mesh.createTACS(varsPerNode)

    # Set the traction load into the assembler object
    aux = TACS.AuxElements(assembler)
    for k in range(num_domains, num_components):
        mesh.addAuxElement(aux, k, traction)
    assembler.setAuxElements(aux)

    return assembler, num_domains