示例#1
0
    def test_first_example(self):
        import math
        import numpy
        from numpy import array
        from spyfe.materials.mat_heatdiff import MatHeatDiff
        from spyfe.fesets.surfacelike import FESetT3
        from spyfe.femms.femm_heatdiff import FEMMHeatDiff
        from spyfe.fields.nodal_field import NodalField
        from spyfe.integ_rules import TriRule
        from spyfe.fenode_set import FENodeSet
        # These are the constants in the problem, k is kappa
        a = 2.5  # radius on the columnthe
        dy = a / 2 * math.sin(15. / 180 * math.pi)
        dx = a / 2 * math.cos(15. / 180 * math.pi)
        Q = 4.5  # internal heat generation rate
        k = 1.8  # thermal conductivity
        m = MatHeatDiff(thermal_conductivity=array([[k, 0.0], [0.0, k]]))
        Dz = 1.0  # thickness of the slice
        xall = array([[0, 0], [dx, -dy], [dx, dy], [2 * dx, -2 * dy],
                      [2 * dx, 2 * dy]])
        fes = FESetT3(array([[1, 2, 3], [2, 4, 5], [2, 5, 3]]) - 1)

        femm = FEMMHeatDiff(material=m,
                            fes=fes,
                            integration_rule=TriRule(npts=1))
        fens = FENodeSet(xyz=xall)
        geom = NodalField(fens=fens)
        temp = NodalField(nfens=xall.shape[0], dim=1)
        temp.set_ebc([3, 4])
        temp.apply_ebc()
        temp.numberdofs(node_perm=[1, 2, 0, 4, 3])
        print(temp.dofnums)
        K = femm.conductivity(geom, temp)
        print(K)
示例#2
0
 def test_fens_1(self):
     import math
     import numpy
     from spyfe.fenode_set import FENodeSet
     a = 2.5  # radius on the columnthe
     dy = a / 2 * math.sin(15. / 180 * math.pi)
     dx = a / 2 * math.cos(15. / 180 * math.pi)
     fens = FENodeSet(xyz=numpy.array([[0, 0], [dx, -dy], [dx, dy],
                                       [2 * dx, -2 * dy], [2 * dx, 2 *
                                                           dy]]))
     print(fens.xyz)
示例#3
0
def t3_ablock(Length, Width, nL, nW):
    """
    Mesh of T3 elements of a rectangle.  Alternate orientation.

    :param Length:
    :param Width:
    :param nL:
    :param nW:
    :param options:
    :return:

    See also:  T3_blocku, T3_cblock,   T3_crossblock, T3_ablock,
               T3_ablockc, T3_ablockn, T3_block, T3_blockc, T3_blockn
    """
    nnodes = (nL + 1) * (nW + 1)
    ncells = 2 * (nL) * (nW)
    xs = OneBased2DArray((nnodes, 2))
    conns = OneBased2DArray((ncells, 3), dtype=int)
    f = 1
    for j in range_1based(1, (nW + 1)):
        for i in range_1based(1, (nL + 1)):
            xs[f, 0], xs[f, 1] = (i - 1) * Length / nL, (j - 1) * Width / nW
            f += 1

    fens = FENodeSet(xs.raw_array())

    def node_numbers1(i, j, nL, nW):
        f = (j - 1) * (nL + 1) + i
        return array([f, (f + 1), f + (nL + 1) + 1])

    def node_numbers2(i, j, nL, nW):
        f = (j - 1) * (nL + 1) + i
        return array([f, f + (nL + 1) + 1, f + (nL + 1)])

    gc = 1
    for i in range_1based(1, nL):
        for j in range_1based(1, nW):
            nn = node_numbers1(i, j, nL, nW)
            conns[gc, :] = nn[:]
            gc += 1
            nn = node_numbers2(i, j, nL, nW)
            conns[gc, :] = nn[:]
            gc += 1

    fes = FESetT3(conn=conns.raw_array() - 1)

    return fens, fes
示例#4
0
def h8_blockx(xs, ys, zs):
    """
    Mesh of H8 elements of a rectangular 3D block.

    Mesh of a 3-D block, H8 finite elements. The nodes are located at the
    Cartesian product of the three intervals on the input.  This allows for
    construction of graded meshes.
    :param xs: array of the X coordinates of the nodes
    :param ys: array of the Y coordinates of the nodes
    :param zs: array of the Z coordinates of the nodes
    :return: fens, fes

    See also:
    """
    nL = len(xs) - 1
    nW = len(ys) - 1
    nH = len(zs) - 1
    nnodes = (nL + 1) * (nW + 1) * (nH + 1)
    ncells = (nL) * (nW) * (nH)
    X = OneBased2DArray((nnodes, 3))
    f = 1
    for k in range_1based(1, (nH + 1)):
        for j in range_1based(1, (nW + 1)):
            for i in range_1based(1, (nL + 1)):
                X[f, 0], X[f, 1], X[f, 2] = xs[i - 1], ys[j - 1], zs[k - 1]
                f += 1

    fens = FENodeSet(X.raw_array())

    def node_numbers(i, j, k, nL, nW, nH):
        lf = (k - 1) * ((nL + 1) * (nW + 1)) + (j - 1) * (nL + 1) + i
        an = array([lf, (lf + 1), lf + (nL + 1) + 1, lf + (nL + 1)])
        return hstack((an, an + ((nL + 1) * (nW + 1))))

    conns = OneBased2DArray((ncells, 8), dtype=int)
    gc = 1
    for i in range_1based(1, nL):
        for j in range_1based(1, nW):
            for k in range_1based(1, nH):
                nn = node_numbers(i, j, k, nL, nW, nH)
                conns[gc, :] = nn[:]
                gc += 1

    fes = FESetH8(conn=conns.raw_array() - 1)

    return fens, fes
示例#5
0
def q4_blockx(xs, ys):
    """
    Mesh of Q4 elements of a rectangle.

    Mesh of a 2-D block, Q4 finite elements. The nodes are located at the
    Cartesian product of the two intervals on the input.  This allows for
    construction of graded meshes.
    :param xs: array of the X coordinates of the nodes
    :param ys: array of the Y coordinates of the nodes
    :return: fens, fes

    See also:
    """
    nL = len(xs) - 1
    nW = len(ys) - 1
    nnodes = (nL + 1) * (nW + 1)
    ncells = (nL) * (nW)
    X = OneBased2DArray((nnodes, 2))
    f = 1
    for j in range_1based(1, (nW + 1)):
        for i in range_1based(1, (nL + 1)):
            X[f, 0], X[f, 1] = xs[i - 1], ys[j - 1]
            f += 1

    fens = FENodeSet(X.raw_array())

    def node_numbers(i, j, nL, nW):
        f = (j - 1) * (nL + 1) + i
        return array([f, (f + 1), f + (nL + 1) + 1, f + (nL + 1)]).ravel()

    conns = OneBased2DArray((ncells, 4), dtype=int)
    gc = 1
    for i in range_1based(1, nL):
        for j in range_1based(1, nW):
            nn = node_numbers(i, j, nL, nW)
            conns[gc, :] = nn[:]
            gc += 1

    fes = FESetQ4(conn=conns.raw_array() - 1)

    return fens, fes
示例#6
0
def import_mesh(filename):
    """Import Abaqus mesh.
    
    Import tetrahedral (4- and 10-node) or hexahedral (8- and 20-node) ABAQUS Mesh (.INP).
    Limitations: only the *NODE and *ELEMENT  sections are read. Only 3D elements are handled.
    :param filename: 
    :return: fens, feslist
    """

    f = open(filename, 'r')

    chunk = 1000
    node = numpy.zeros((chunk, 4))

    # Find the node section
    while True:
        temp = f.readline()
        if temp == '':
            f.close()
            raise Exception('No nodes in mesh file?')
        temp = temp.strip()
        if temp[0:5].upper() == '*NODE':
            break  # now we process the *NODE section

    # We have the node section, now we need to read the data
    nnode = 0
    while True:
        temp = f.readline()
        temp = temp.strip()
        if temp[0] == '*':
            break  # done with reading nodes
        A = temp.replace(',', ' ').split()
        node[nnode, :] = float(A[0]), float(A[1]), float(A[2]), float(A[3])
        nnode = nnode + 1
        if nnode >= node.shape[0]:
            node = numpy.vstack(
                (node, numpy.zeros((node.shape[1] + chunk, node.shape[1]))))

    # Now find and process all *ELEMENT blocks
    More_data = True
    elsets = []
    while More_data:
        # Find the next block
        while temp[0] != '*':
            if len(temp) >= 8 and temp.upper()[0:8] == '*ELEMENT':
                break  # got it
            temp = f.readline()
            if temp == '':
                f.close()
                More_data = False
                break
            temp = temp.strip()

        Valid, Type, Elset = _Parse_element_line(temp)

        if (Valid):  # Valid element type
            nelem = 0
            ennod = Type
            elem = numpy.zeros((chunk, ennod), dtype=int)
            while True:
                temp = f.readline()
                if temp == '':
                    f.close()
                    More_data = False
                    break
                if temp[0] == '*':
                    elem = elem[0:nelem, :]
                    elsets.append((nelem, copy.deepcopy(elem), Elset))
                    break  # done with reading this element block
                A = temp.replace(',', ' ').split()
                A = A[1:]  # get rid of the element serial number
                for k in range(len(A)):
                    elem[nelem, k] = int(A[k])
                if len(A) < ennod:  # we need to read a continuation line
                    prevn = len(A)
                    temp = f.readline()
                    if temp == '':
                        f.close()
                        raise Exception('Premature end of element line')
                    A = temp.replace(',', ' ').split()
                    for k in range(len(A)):
                        elem[nelem, prevn + k] = int(A[k])
                    if prevn + len(A) != ennod:
                        raise Exception('Wrong number of element nodes')
                nelem += 1
                if nelem >= elem.shape[0]:
                    elem = numpy.vstack(
                        (elem, numpy.zeros((chunk, elem.shape[1]))))
        else:
            temp = f.readline()
            if temp == '':
                More_data = False
                break

    # We are done with the file.
    f.close()
    # Some error checks
    node = node[0:nnode, :]
    if numpy.linalg.norm(numpy.array(numpy.arange(1, nnode + 1)) -
                         node[:, 0]) != 0:
        raise Exception('Nodes are not in serial order')
    # Process output arguments
    # Extract coordinates
    fens = FENodeSet(xyz=node[:, 1:4])
    # Now create all element sets
    feslist = []
    for j, e in enumerate(elsets):
        nelem, elem, ElSet = e
        conn = elem - 1
        if elem.shape[1] == 4:
            fes = FESetT4(conn=conn, label=j)
        elif elem.shape[1] == 10:
            fes = FESetT10(conn=conn, label=j)
        elif elem.shape[1] == 8:
            fes = FESetH8(conn=conn, label=j)
        elif elem.shape[1] == 20:
            fes = FESetH20(conn=conn, label=j)
        feslist.append(fes)

    return fens, feslist
示例#7
0
def import_mesh(filename):
    """Import tetrahedral (4- and 10-node) NASTRAN mesh.

    Limitations:
    1. only the GRID and CTETRA  sections are read.
    2. Only 4-node and 10-node tetrahedra  are handled.
    3.  The file needs to be free-form (data separated by commas).

    :param filename:
    :return:
    """
    f = open(filename, 'r')

    chunk = 5000
    nnode = 0
    node = numpy.zeros((chunk, 4))
    nelem = 0
    elem = numpy.zeros((chunk, 13), dtype=int)
    ennod = []

    while True:
        temp = f.readline()
        if temp == '':
            f.close()
            break
        temp = temp.strip()
        if temp.upper()[0:4] == 'GRID':
            # Template:
            #   GRID,1,,-1.32846E-017,3.25378E-033,0.216954
            A = temp.replace(',', ' ').split()
            node[nnode, :] = float(A[1]), float(A[2]), float(A[3]), float(A[4])
            nnode = nnode + 1
            if nnode >= node.shape[0]:
                node = numpy.vstack((node, numpy.zeros(
                    (chunk, node.shape[1]))))
        elif temp.upper()[0:6] == 'CTETRA':
            # Template:
            #                 CTETRA,1,3,15,14,12,16,8971,4853,8972,4850,8973,4848
            A = temp.replace(',', ' ').split()
            elem[nelem, 0] = int(A[1])
            elem[nelem, 1] = int(A[2])
            if len(A) == 7:  #  nodes per element  equals  4
                nperel = 4
            else:  # nodes per element equals 10
                nperel = 10
                if len(A) < 13:  # the line is continued: read the next line
                    addtemp = f.readline()
                    addA = addtemp.replace(',', ' ').split()
                    A = A[3:] + addA
            for k in range(nperel):
                elem[nelem, k + 3] = int(A[k + 3])
            elem[nelem, 2] = nperel
            nelem = nelem + 1
            if nelem >= elem.shape[0]:
                elem = numpy.vstack((elem, numpy.zeros(
                    (chunk, elem.shape[1]))))

    node = node[0:nnode, :]
    elem = elem[0:nelem, :]

    if numpy.linalg.norm(numpy.array(numpy.arange(1, nnode + 1)) -
                         node[:, 0]) != 0:
        raise Exception('Nodes are not in serial order')

    # Process output arguments
    # Extract coordinates
    xyz = node[:, 1:4]

    # Cleanup element connectivities
    ennod = numpy.unique(elem[:, 2])
    if len(ennod) != 1:
        raise Exception(
            'This function cannot treat a mixture of element types at this point'
        )

    if (ennod[0] != 4) and (ennod[0] != 10):
        raise Exception('Unknown element type')

    # Compensate for the Python indexing: make the connectivities zero-based
    conn = elem[:, 3:3 + ennod[0]] - 1
    label = elem[:, 1]

    # Create output arguments. First the nodes
    fens = FENodeSet(xyz=xyz)

    # Now the geometric cells for each element set
    if ennod[0] == 4:
        fes = FESetT4(conn=conn, label=label)
    else:
        fes = FESetT10(conn=conn, label=label)

    return fens, [fes]
示例#8
0
def t4_blockx(xs, ys, zs, orientation='a'):
    """Graded tetrahedral (T4) mesh of a rectangular block.
    
    :param xs: 
    :param ys: 
    :param zs: 
    :param orientation: 'a', 'b', 'ca', 'cb'
    :return: 
    """

    nL = len(xs) - 1
    nW = len(ys) - 1
    nH = len(zs) - 1
    nnodes = (nL + 1) * (nW + 1) * (nH + 1)
    xyzs = OneBased2DArray((nnodes, 3))

    if (orientation == 'a'):
        t4ia = numpy.array([[1, 8, 5, 6], [3, 4, 2, 7], [7, 2, 6, 8],
                            [4, 7, 8, 2], [2, 1, 6, 8], [4, 8, 1, 2]]) - 1
        t4ib = numpy.array([[1, 8, 5, 6], [3, 4, 2, 7], [7, 2, 6, 8],
                            [4, 7, 8, 2], [2, 1, 6, 8], [4, 8, 1, 2]]) - 1
    elif (orientation == 'b'):
        t4ia = numpy.array([[2, 7, 5, 6], [1, 8, 5, 7], [1, 3, 4, 8],
                            [2, 1, 5, 7], [1, 2, 3, 7], [3, 7, 8, 1]]) - 1
        t4ib = numpy.array([[2, 7, 5, 6], [1, 8, 5, 7], [1, 3, 4, 8],
                            [2, 1, 5, 7], [1, 2, 3, 7], [3, 7, 8, 1]]) - 1
    elif (orientation == 'ca'):
        t4ia = numpy.array([[8, 4, 7, 5], [6, 7, 2, 5], [3, 4, 2, 7],
                            [1, 2, 4, 5], [7, 4, 2, 5]]) - 1
        t4ib = numpy.array([[7, 3, 6, 8], [5, 8, 6, 1], [2, 3, 1, 6],
                            [4, 1, 3, 8], [6, 3, 1, 8]]) - 1
    elif (orientation == 'cb'):
        t4ib = numpy.array([[8, 4, 7, 5], [6, 7, 2, 5], [3, 4, 2, 7],
                            [1, 2, 4, 5], [7, 4, 2, 5]]) - 1
        t4ia = numpy.array([[7, 3, 6, 8], [5, 8, 6, 1], [2, 3, 1, 6],
                            [4, 1, 3, 8], [6, 3, 1, 8]]) - 1
    else:
        raise Exception('Unknown orientation')

    ncells = t4ia.shape[0] * (nL) * (nW) * (nH)
    conns = OneBased2DArray((ncells, 4))

    f = 1
    for k in range_1based(1, nH + 1):
        for j in range_1based(1, nW + 1):
            for i in range_1based(1, nL + 1):
                xyzs[f, :] = xs[i - 1], ys[j - 1], zs[k - 1]
                f += 1

    fens = FENodeSet(xyzs.raw_array())

    def node_numbers(i, j, k, nL, nW, nH):
        f = (k - 1) * ((nL + 1) * (nW + 1)) + (j - 1) * (nL + 1) + i
        return array([
            f, (f + 1), f + (nL + 1) + 1, f + (nL + 1),
            f + ((nL + 1) * (nW + 1)), (f + 1) + ((nL + 1) * (nW + 1)),
            f + (nL + 1) + 1 + ((nL + 1) * (nW + 1)),
            f + (nL + 1) + ((nL + 1) * (nW + 1))
        ])

    gc = 1
    for i in range_1based(1, nL):
        for j in range_1based(1, nW):
            for k in range_1based(1, nH):
                nn = node_numbers(i, j, k, nL, nW, nH)
                if ((i + j + k) % 2 == 0):
                    t4i = t4ib
                else:
                    t4i = t4ia
                for r in range(t4i.shape[0]):
                    conns[gc, :] = nn[t4i[r, :]]
                    gc += 1

    c = numpy.array(conns.raw_array() - 1, dtype=int)
    fes = FESetT4(conn=c)
    return fens, fes
示例#9
0
def fuse_nodes(fens1, fens2, tolerance=0.0):
    # Fuse together nodes from to node sets.
    #
    # function [fens,new_indexes_of_fens1_nodes] = fuse_nodes(fens1, fens2, tolerance)
    #
    # Fuse two node sets. If necessary, by gluing together nodes located within tolerance of each other.
    # The two node sets, fens1 and fens2,  are fused together by
    # merging the nodes that fall within a box of size "tolerance".
    # The merged node set, fens, and the new  indexes of the nodes
    # in the set fens1 are returned.
    #
    # The set fens2 will be included unchanged, in the same order,
    # in the node set fens.
    #
    # The indexes of the node set fens1 will have changed.
    #
    # Example:
    # After the call to this function we have
    # k=new_indexes_of_fens1_nodes(j) is the node in the node set fens which
    # used to be node j in node set fens1.
    # The finite element set connectivity that used to refer to fens1
    # needs to be updated to refer to the same nodes in  the set fens as
    #     fes = update_conn(fes ,new_indexes_of_fens1_nodes)
    #
    # See also: merge_nodes, update_conn
    #

    # I need to have the node number as non-zero to mark the replacement
    # when fused
    xyz1 = fens1.xyz
    id1 = numpy.array(range(1, fens1.count() + 1))
    xyz2 = fens2.xyz
    id2 = numpy.array(range(1, fens2.count() + 1))
    c1 = numpy.ones((xyz2.shape[0], 1))  # column matrix
    # Mark nodes from the first array that are duplicated in the second
    if (tolerance > 0):  # should we attempt to merge nodes?
        Box2 = inflate_box(bounding_box(xyz2), tolerance)
        for i in range(fens1.count()):
            XYZ = xyz1[i, :].reshape(1, xyz1.shape[1])  # row matrix
            # Note  that we are looking for  distances  of this node to nodes in the OTHER node set
            if in_box(Box2, XYZ):  # This check makes this run much faster
                xyzd = abs(
                    xyz2 - c1 *
                    XYZ)  # find the distances along  coordinate directions
                dist = numpy.sum(xyzd, axis=1)
                jx = dist < tolerance
                if numpy.any(jx):
                    minn = numpy.argmin(dist)
                    id1[i] = -id2[minn]

    # Generate  fused arrays of the nodes
    xyzm = numpy.zeros((fens1.count() + fens2.count(), xyz1.shape[1]))
    xyzm[0:fens2.count(), :] = xyz2  # fens2 are there without change
    mid = fens2.count() + 1
    for i in range(
            fens1.count()):  # and then we pick only non-duplicated fens1
        if id1[i] > 0:
            id1[i] = mid
            xyzm[mid - 1, :] = xyz1[i, :]
            mid = mid + 1
        else:
            id1[i] = id2[-id1[i] - 1]

    nfens = mid - 1
    xyzm = xyzm[0:nfens, :]

    # Create the fused Node set
    fens = FENodeSet(xyz=xyzm)
    # The Node set 1 numbering will change
    new_indexes_of_fens1_nodes = id1 - 1  # go back to zero-based indexes
    # The node set 2 numbering stays the same, node set 1 will need to be
    # renumbered
    return fens, new_indexes_of_fens1_nodes
示例#10
0
def q4_to_q8(fens, fes):
    """
    
    :param fens:
    :param fes:
    :return:
    """
    # Convert a mesh of quadrilateral Q4 to quadrilateral Q8.
    #
    # function [fens,fes] = Q4_to_Q8(fens,fes,options)
    #
    # options =attributes recognized by the constructor fe_set_Q8
    #
    # Examples:
    #     R=8.5
    #     [fens,fes]=Q4_sphere(R,1,1.0)
    #     [fens,fes] = Q4_to_Q8(fens,fes,[])
    #     fens= onto_sphere(fens,R,[])
    #     drawmesh({fens,fes},'nodes','fes','facecolor','y', 'linewidth',2) hold on
    #
    # See also: fe_set_Q8

    nedges = 4
    ec = array([[0, 1], [1, 2], [2, 3], [3, 0]])
    # make a search structure for edges
    edges = {}
    for i in range(fes.conn.shape[0]):
        conn = fes.conn[i, :]
        for J in range(nedges):
            ev = conn[ec[J, :]]
            anchor = numpy.amin(ev)
            otherv = numpy.amax(ev)
            if anchor not in edges:
                edges[anchor] = set([otherv])
            else:
                edges[anchor].add(otherv)

    # now generate new node number for each edge
    nodes = copy.deepcopy(edges)
    n = fens.count()
    for anchor, othervs in edges.items():
        nnew = []
        for index in othervs:
            nnew.append(n)
            n += 1
        nodes[anchor] = nnew

    xyz1 = fens.xyz
    xyz = numpy.zeros((n, xyz1.shape[1]))
    xyz[0:xyz1.shape[0], :] = xyz1[:, :]
    # calculate the locations of the new nodes
    # and construct the new nodes
    for anchor, othervs in edges.items():
        nnew = nodes[anchor]
        othervs = list(othervs)
        for J in range(len(othervs)):
            e = othervs[J]
            xyz[nnew[J], :] = (xyz[anchor, :] + xyz[e, :]) / 2

    # construct new finite elements
    nconns = numpy.zeros((fes.count(), 8), dtype=int)
    for i in range(fes.conn.shape[0]):
        conn = fes.conn[i, :]
        econn = numpy.zeros((nedges, ))
        for J in range(nedges):
            ev = conn[ec[J, :]]
            anchor = numpy.amin(ev)
            otherv = numpy.amax(ev)
            nnew = nodes[anchor]
            othervs = list(edges[anchor])
            for k in range(len(othervs)):
                if othervs[k] == otherv:
                    econn[J] = nnew[k]
                    break
        nconns[i, 0:4] = conn
        nconns[i, 4:8] = econn

    fens = FENodeSet(xyz)
    fes = FESetQ8(conn=nconns, label=fes.label)
    return fens, fes