コード例 #1
0
ファイル: drx.py プロジェクト: dtbinh/T1_python-exercises
def _beam_shear(S, X, inds, indi, indf, EIx, EIy):
    """ Generate the beam nodal shear forces Sx, Sy and Sz.

    Parameters:
        S (array): Empty or populated beam nodal shear force array.
        X (array): Co-ordinates of nodes.
        inds (list): Indices of all beam element start nodes.
        indi (list): Indices of all beam element intermediate nodes.
        indf (list): Indices of all beam element finish nodes beams.
        EIx (array): Nodal EIx flexural stiffnesses for all beams.
        EIy (array): Nodal EIy flexural stiffnesses for all beams.

    Returns:
        array: Updated beam nodal shears.
    """
    S *= 0
    Xs = X[inds, :]
    Xi = X[indi, :]
    Xf = X[indf, :]
    Qa = Xi - Xs
    Qb = Xf - Xi
    Qc = Xf - Xs
    Qn = cross(Qa, Qb)
    Qnn = normrow(Qn)
    La = normrow(Qa)
    Lb = normrow(Qb)
    Lc = normrow(Qc)
    a = arccos((La**2 + Lb**2 - Lc**2) / (2 * La * Lb))
    k = 2 * sin(a) / Lc
    mu = -0.5 * Xs + 0.5 * Xf
    mun = normrow(mu)
    ex = Qn / tile(Qnn, (1, 3))  # Temporary simplification
    ez = mu / tile(mun, (1, 3))
    ey = cross(ez, ex)
    K = tile(k / Qnn, (1, 3)) * Qn
    Kx = tile(sum(K * ex, 1)[:, newaxis], (1, 3)) * ex
    Ky = tile(sum(K * ey, 1)[:, newaxis], (1, 3)) * ey
    Mc = EIx * Kx + EIy * Ky
    cma = cross(Mc, Qa)
    cmb = cross(Mc, Qb)
    ua = cma / tile(normrow(cma), (1, 3))
    ub = cmb / tile(normrow(cmb), (1, 3))
    c1 = cross(Qa, ua)
    c2 = cross(Qb, ub)
    Lc1 = normrow(c1)
    Lc2 = normrow(c2)
    M = sum(Mc**2, 1)[:, newaxis]
    Sa = ua * tile(M * Lc1 / (La * sum(Mc * c1, 1)[:, newaxis]), (1, 3))
    Sb = ub * tile(M * Lc2 / (Lb * sum(Mc * c2, 1)[:, newaxis]), (1, 3))
    Sa[isnan(Sa)] = 0
    Sb[isnan(Sb)] = 0
    S[inds, :] += Sa
    S[indi, :] += -Sa - Sb
    S[indf, :] += Sb
    # Add node junction duplication for when elements cross each other
    # mu[0, :] = -1.25*x[0, :] + 1.5*x[1, :] - 0.25*x[2, :]
    # mu[-1, :] = 0.25*x[-3, :] - 1.5*x[-2, :] + 1.25*x[-1, :]
    return S
コード例 #2
0
ファイル: fd.py プロジェクト: dtbinh/T1_python-exercises
def fd(vertices, edges, fixed, q, loads, rtype='list'):
    num_v     = len(vertices)
    free      = list(set(range(num_v)) - set(fixed))
    xyz       = asarray(vertices, dtype=float).reshape((-1, 3))
    q         = asarray(q, dtype=float).reshape((-1, 1))
    p         = asarray(loads, dtype=float).reshape((-1, 3))
    C         = connectivity_matrix(edges, 'csr')
    Ci        = C[:, free]
    Cf        = C[:, fixed]
    Ct        = C.transpose()
    Cit       = Ci.transpose()
    Q         = diags([q.flatten()], [0])
    A         = Cit.dot(Q).dot(Ci)
    b         = p[free] - Cit.dot(Q).dot(Cf).dot(xyz[fixed])
    xyz[free] = spsolve(A, b)
    l         = normrow(C.dot(xyz))
    f         = q * l
    r         = p - Ct.dot(Q).dot(C).dot(xyz)
    if rtype == 'list':
        return [xyz.tolist(),
                q.ravel().tolist(),
                f.ravel().tolist(),
                l.ravel().tolist(),
                r.tolist()]
    if rtype == 'dict':
        return {'xyz': xyz.tolist(),
                'q'  : q.ravel().tolist(),
                'f'  : f.ravel().tolist(),
                'l'  : l.ravel().tolist(),
                'r'  : r.tolist()}
    return xyz, q, f, l, r
コード例 #3
0
def grad(V, F, rtype='array'):
    """Construct the gradient operator of a trianglular mesh.

    Parameters
    ----------
    V : array
        Vertex coordinates of the mesh.
    F : array
        Face vertex indices of the mesh.
    rtype : {'array', 'csc', 'csr', 'coo', 'list'}
        Format of the result.

    Returns
    -------
    array-like
        Depending on rtype return type.

    Notes
    -----
    The gradient operator is fully determined by the connectivity of the mesh
    and the coordinate difference vectors associated with the edges

    """
    v = V.shape[0]
    f = F.shape[0]
    f0 = F[:, 0]  # Index of first vertex of each face
    f1 = F[:, 1]  # Index of second vertex of each face
    f2 = F[:, 2]  # Index of last vertex of each face
    v01 = V[f1, :] - V[f0, :]  # Vector from vertex 0 to 1 for each face
    v12 = V[f2, :] - V[f1, :]  # Vector from vertex 1 to 2 for each face
    v20 = V[f0, :] - V[f2, :]  # Vector from vertex 2 to 0 for each face
    n = cross(v12, v20)  # Normal vector to each face
    A2 = normrow(n)  # Length of normal vector is twice the area of the face
    A2 = tile(A2, (1, 3))
    u = normalizerow(n)  # Unit normals for each face
    v01_ = divide(rot90(v01, u),
                  A2)  # Vector perpendicular to v01, normalized by A2
    v20_ = divide(rot90(v20, u),
                  A2)  # Vector perpendicular to v20, normalized by A2
    i = hstack((  # Nonzero rows
        0 * f + tile(arange(f), (1, 4)), 1 * f + tile(arange(f), (1, 4)),
        2 * f + tile(arange(f), (1, 4)))).flatten()
    j = tile(hstack((f1, f0, f2, f0)), (1, 3)).flatten()  # Nonzero columns
    data = hstack((
        hstack((v20_[:, 0], -v20_[:, 0], v01_[:, 0], -v01_[:, 0])),
        hstack((v20_[:, 1], -v20_[:, 1], v01_[:, 1], -v01_[:, 1])),
        hstack((v20_[:, 2], -v20_[:, 2], v01_[:, 2], -v01_[:, 2])),
    )).flatten()
    G = coo_matrix((data, (i, j)), shape=(3 * f, v))
    if rtype == 'array':
        return G.toarray()
    elif rtype == 'csr':
        return G.tocsr()
    elif rtype == 'csc':
        return G.tocsc()
    elif rtype == 'coo':
        return G
    else:
        return G
コード例 #4
0
def fn(l0, *args):
    tol, Xt, edges = args
    for c, uv in enumerate(edges):
        network.set_edge_attribute(uv[0], uv[1], 'l0', l0[c])
    X, f, l = numba_dr_run(network, tol=tol)
    X[:, 2] /= max(X[:, 2])
    norm = mean(normrow(X - Xt))
    if isnan(norm) or isinf(norm):
        return 10**6
    return norm
コード例 #5
0
def uvw_lengths(C, X):
    r"""Calculates the lengths and co-ordinate differences.

    Parameters:
        C (sparse): Connectivity matrix (m x n)
        X (array): Co-ordinates of vertices/points (n x 3).

    Returns:
        array: Vectors of co-ordinate differences in x, y and z (m x 3).
        array: Lengths of members (m x 1)

    Examples:
        >>> C = connectivity_matrix([[0, 1], [1, 2]], 'csr')
        >>> X = array([[0, 0, 0], [1, 1, 0], [0, 0, 1]])
        >>> uvw
        array([[ 1,  1,  0],
               [-1, -1,  1]])
        >>> l
        array([[ 1.41421356],
               [ 1.73205081]])
    """
    uvw = C.dot(X)
    return uvw, normrow(uvw)
コード例 #6
0
ファイル: drx.py プロジェクト: dtbinh/T1_python-exercises
def _create_arrays(network):
    """ Create arrays needed for dr_solver.

    Parameters:
        network (obj): Network to analyse.

    Returns:
        array: Constraint conditions.
        array: Nodal loads Px, Py, Pz.
        array: Resultant nodal loads.
        array: Sx, Sy, Sz shear force components.
        array: x, y, z co-ordinates.
        array: Nodal velocities Vx, Vy, Vz.
        array: Edges' initial forces.
        array: Edges' initial lengths.
        list: Compression only edges.
        list: Tension only edges.
        array: Connectivity matrix.
        array: Transposed connectivity matrix.
        array: Axial stiffnesses.
        array: Network edges' start points.
        array: Network edges' end points.
        array: Mass matrix.
        list: Edge adjacencies (rows).
        list: Edge adjacencies (columns).
        list: Edge adjacencies (values).
        array: Young's moduli.
        array: Edge areas.
    """

    # Vertices

    n = network.number_of_vertices()
    B = zeros((n, 3))
    P = zeros((n, 3))
    X = zeros((n, 3))
    S = zeros((n, 3))
    V = zeros((n, 3))
    k_i = network.key_index()
    for key in network.vertices():
        i = k_i[key]
        vertex = network.vertex[key]
        B[i, :] = vertex['B']
        P[i, :] = vertex['P']
        X[i, :] = [vertex[j] for j in 'xyz']
    Pn = normrow(P)

    # Edges

    m = len(network.edges())
    E = zeros((m, 1))
    A = zeros((m, 1))
    s0 = zeros((m, 1))
    l0 = zeros((m, 1))
    u = []
    v = []
    ind_c = []
    ind_t = []
    edges = []
    uv_i = network.uv_index()
    for ui, vi in network.edges():
        i = uv_i[(ui, vi)]
        edge = network.edge[ui][vi]
        edges.append([k_i[ui], k_i[vi]])
        u.append(k_i[ui])
        v.append(k_i[vi])
        E[i] = edge['E']
        A[i] = edge['A']
        s0[i] = edge['s0']
        if edge['l0']:
            l0[i] = edge['l0']
        else:
            l0[i] = network.edge_length(ui, vi)
        if edge['ct'] == 'c':
            ind_c.append(i)
        elif edge['ct'] == 't':
            ind_t.append(i)
    f0 = s0 * A
    ks = E * A / l0

    # Arrays

    C = connectivity_matrix(edges, 'csr')
    Ct = C.transpose()
    M = mass_matrix(Ct, E, A, l0, f0, c=1, tiled=False)
    rows, cols, vals = find(Ct)

    return B, P, Pn, S, X, V, f0, l0, ind_c, ind_t, C, Ct, ks, array(u), array(
        v), M, rows, cols, vals, E, A
コード例 #7
0
ファイル: drx.py プロジェクト: dtbinh/T1_python-exercises
def drx_numpy(tol,
              steps,
              C,
              Ct,
              V,
              M,
              B,
              S,
              P,
              X,
              f0,
              ks,
              l0,
              ind_c,
              ind_t,
              refresh,
              factor=1,
              beams=None,
              inds=None,
              indi=None,
              indf=None,
              EIx=None,
              EIy=None):
    """ Numpy and SciPy dynamic relaxation solver.

    Parameters:
        tol (float): Tolerance limit.
        steps (int): Maximum number of iteration steps.
        C (array): Connectivity matrix.
        Ct (array): Transposed connectivity matrix.
        V (array): Nodal velocities Vx, Vy, Vz.
        M (array): Mass matrix (untiled).
        B (array): Constraint conditions.
        S (array): Sx, Sy, Sz shear force components.
        P (array): Nodal loads Px, Py, Pz.
        X (array): Nodal co-ordinates.
        f0 (array): Initial edge forces.
        ks (array): Initial edge stiffnesses.
        l0 (array): Initial edge lengths.
        ind_c (list): Compression only edges.
        ind_t (list): Tension only edges.
        refresh (int): Update progress every n steps.
        factor (float): Convergence factor.
        beams (dic): Dictionary of beam information.
        inds (list): Indices of all beam element start nodes.
        indi (list): Indices of all beam element intermediate nodes.
        indf (list): Indices of all beam element finish nodes beams.
        EIx (array): Nodal EIx flexural stiffnesses for all beams.
        EIy (array): Nodal EIy flexural stiffnesses for all beams.

    Returns:
        array: Updated nodal co-ordinates.
        array: Final forces.
        array: Final lengths.
    """
    res = 1000 * tol
    ts, Uo = 0, 0
    M = factor * tile(M, (1, 3))
    while (ts <= steps) and (res > tol):
        uvw, l = uvw_lengths(C, X)
        f = f0 + ks * (l - l0)
        if ind_t:
            f[ind_t] *= f[ind_t] > 0
        if ind_c:
            f[ind_c] *= f[ind_c] < 0
        if beams:
            S = _beam_shear(S, X, inds, indi, indf, EIx, EIy)
        q = tile(f / l, (1, 3))
        R = (P - S - Ct.dot(uvw * q)) * B
        Rn = normrow(R)
        res = mean(Rn)
        V += R / M
        Un = sum(0.5 * M * V**2)
        if Un < Uo:
            V *= 0
        Uo = Un
        X += V
        ts += 1
    if refresh:
        print('Iterations: {0}'.format(ts - 1))
        print('Residual: {0:.3g}'.format(res))
    return X, f, l
コード例 #8
0
def dr_solver(tol, steps, factor, C, Ct, X, ks, l0, f0, ind_c, ind_t, P, S, B,
              M, V, refresh, bmesh, beams, inds, indi, indf, EIx, EIy):
    """ Numpy and SciPy dynamic relaxation solver.

    Parameters:
        tol (float): Tolerance limit.
        steps (int): Maximum number of iteration steps.
        factor (float): Convergence factor.
        C (array): Connectivity matrix.
        Ct (array): Transposed connectivity matrix.
        X (array): Nodal co-ordinates.
        ks (array): Initial edge axial stiffnesses.
        l0 (array): Initial edge lengths.
        f0 (array): Initial edge forces.
        ind_c (list): Compression only edges.
        ind_t (list): Tension only edges.
        P (array): Nodal loads Px, Py, Pz.
        S (array): Shear forces Sx, Sy, Sz.
        B (array): Constraint conditions.
        M (array): Mass matrix (untiled).
        V (array): Nodal velocities Vx, Vy, Vz.
        refresh (int): Update progress every n steps.
        bmesh (obj): Blender mesh to update.
        beams (bool): Dictionary of beam information.
        inds (list): Indices of beam element start nodes.
        indi (list): Indices of beam element intermediate nodes.
        indf (list): Indices of beam element finish nodes beams.
        EIx (array): Nodal EIx flexural stiffnesses.
        EIy (array): Nodal EIy flexural stiffnesses.

    Returns:
        array: Updated nodal co-ordinates.
        array: Final edge forces.
        array: Final edge lengths.
    """
    res = 1000 * tol
    ts = 0
    Uo = 0
    M = factor * tile(M, (1, 3))
    while (ts <= steps) and (res > tol):
        uvw, l = uvw_lengths(C, X)
        f = f0 + ks * (l - l0)
        if ind_t:
            f[ind_t] *= f[ind_t] > 0
        if ind_c:
            f[ind_c] *= f[ind_c] < 0
        if beams:
            S = beam_shear(S, X, inds, indi, indf, EIx, EIy)
        q = f / l
        qt = tile(q, (1, 3))
        R = (P - S - Ct.dot(uvw * qt)) * B
        res = mean(normrow(R))
        V += R / M
        Un = sum(M * V**2)
        if Un < Uo:
            V *= 0
        Uo = Un
        X += V
        if refresh and (ts % refresh == 0):
            print('Step:{0} Residual:{1:.3g}'.format(ts, res))
            if bmesh:
                update_bmesh_vertices(bmesh, X)
        ts += 1
    if refresh:
        print('Step:{0} Residual:{1:.3g}'.format(ts, res))
    return X, f, l
コード例 #9
0
def create_arrays(network):
    """ Create arrays for DR solver.

    Parameters:
        network (obj): Network to analyse.

    Returns:
        array: Nodal co-ordinates x, y, z.
        array: Constraint conditions Bx, By, Bz.
        array: Nodal loads Px, Py, Pz.
        array: Resultant nodal loads.
        array: Shear force components Sx, Sy, Sz.
        array: Nodal velocities Vx, Vy, Vz.
        array: Edge Young's moduli.
        array: Edge areas.
        array: Connectivity matrix.
        array: Transposed connectivity matrix.
        array: Edge initial forces.
        array: Edge initial lengths.
        list: Compression only edges indices.
        list: Tension only edges indices.
        array: Network edges' start points.
        array: Network edges' end points.
        array: Mass matrix.
        array: Edge axial stiffnesses.
    """

    # Vertices

    vertices = list(network.vertices())
    n = len(vertices)
    X = zeros((n, 3))
    B = zeros((n, 3))
    P = zeros((n, 3))
    S = zeros((n, 3))
    V = zeros((n, 3))
    k_i = network.key_index()
    for key in vertices:
        i = k_i[key]
        vertex = network.vertex[key]
        X[i, :] = [vertex[j] for j in 'xyz']
        B[i, :] = vertex.get('B', [1, 1, 1])
        P[i, :] = vertex.get('P', [0, 0, 0])
    Pn = normrow(P)

    # Edges

    edges = list(network.edges())
    m = len(edges)
    E = zeros((m, 1))
    A = zeros((m, 1))
    s0 = zeros((m, 1))
    l0 = zeros((m, 1))
    u = zeros(m, dtype=int64)
    v = zeros(m, dtype=int64)
    ind_c = []
    ind_t = []
    uv_i = network.uv_index()
    for c, uv in enumerate(edges):
        ui, vi = uv
        i = uv_i[(ui, vi)]
        edge = network.edge[ui][vi]
        E[i] = edge.get('E', 0)
        A[i] = edge.get('A', 0)
        l0[i] = edge.get('l0', network.edge_length(ui, vi))
        s0[i] = edge.get('s0', 0)
        ct = edge.get('ct', None)
        if ct == 'c':
            ind_c.append(i)
        elif ct == 't':
            ind_t.append(i)
        u[c] = k_i[ui]
        v[c] = k_i[vi]
    f0 = s0 * A
    ks = E * A / l0

    # Faces (unconfirmed testing formulation)

    faces = list(network.faces())
    if faces:
        for face in faces:
            fdata = network.facedata[face]
            Eh = fdata.get('E', 0)
            Ah = network.face_area(face)
            th = fdata.get('t', 0)
            for ui, vi in network.face_edges(face):
                i = uv_i[(ui, vi)]
                ks[i] += 1.5 * Eh * Ah * th / l0[i]**2

    # Arrays

    C = connectivity_matrix([[k_i[ui], k_i[vi]] for ui, vi in edges], 'csr')
    Ct = C.transpose()
    M = mass_matrix(Ct, ks, f0, c=1, tiled=False)

    return X, B, P, Pn, S, V, E, A, C, Ct, f0, l0, ind_c, ind_t, u, v, M, ks
コード例 #10
0
def dr(vertices,
       edges,
       fixed,
       loads,
       qpre,
       fpre,
       lpre,
       linit,
       E,
       radius,
       ufunc=None,
       **kwargs):
    # --------------------------------------------------------------------------
    # configuration
    # --------------------------------------------------------------------------
    kmax = kwargs.get('kmax', 10000)
    dt = kwargs.get('dt', 1.0)
    tol1 = kwargs.get('tol1', 1e-3)
    tol2 = kwargs.get('tol2', 1e-6)
    coeff = Coeff(kwargs.get('c', 0.1))
    ca = coeff.a
    cb = coeff.b
    # --------------------------------------------------------------------------
    # attribute lists
    # --------------------------------------------------------------------------
    num_v = len(vertices)
    num_e = len(edges)
    free = list(set(range(num_v)) - set(fixed))
    # --------------------------------------------------------------------------
    # attribute arrays
    # --------------------------------------------------------------------------
    xyz = array(vertices, dtype=float).reshape((-1, 3))  # m
    p = array(loads, dtype=float).reshape((-1, 3))  # kN
    qpre = array(qpre, dtype=float).reshape((-1, 1))
    fpre = array(fpre, dtype=float).reshape((-1, 1))  # kN
    lpre = array(lpre, dtype=float).reshape((-1, 1))  # m
    linit = array(linit, dtype=float).reshape((-1, 1))  # m
    E = array(E, dtype=float).reshape((-1, 1))  # kN/mm2 => GPa
    radius = array(radius, dtype=float).reshape((-1, 1))  # mm
    # --------------------------------------------------------------------------
    # sectional properties
    # --------------------------------------------------------------------------
    A = 3.14159 * radius**2  # mm2
    EA = E * A  # kN
    # --------------------------------------------------------------------------
    # create the connectivity matrices
    # after spline edges have been aligned
    # --------------------------------------------------------------------------
    C = connectivity_matrix(edges, 'csr')
    Ct = C.transpose()
    Ci = C[:, free]
    Cit = Ci.transpose()
    Ct2 = Ct.copy()
    Ct2.data **= 2
    # --------------------------------------------------------------------------
    # if none of the initial lengths are set,
    # set the initial lengths to the current lengths
    # --------------------------------------------------------------------------
    if all(linit == 0):
        linit = normrow(C.dot(xyz))
    # --------------------------------------------------------------------------
    # initial values
    # --------------------------------------------------------------------------
    q = ones((num_e, 1), dtype=float)
    l = normrow(C.dot(xyz))
    f = q * l
    v = zeros((num_v, 3), dtype=float)
    r = zeros((num_v, 3), dtype=float)

    # --------------------------------------------------------------------------
    # acceleration
    # --------------------------------------------------------------------------
    def a(t, v):
        dx = v * t
        xyz[free] = xyz0[free] + dx[free]
        r[free] = p[free] - D.dot(xyz)
        return cb * r / mass

    # --------------------------------------------------------------------------
    # start iterating
    # --------------------------------------------------------------------------
    for k in xrange(kmax):
        q_fpre = fpre / l
        q_lpre = f / lpre
        q_EA = EA * (l - linit) / (linit * l)
        q_lpre[isinf(q_lpre)] = 0
        q_lpre[isnan(q_lpre)] = 0
        q_EA[isinf(q_EA)] = 0
        q_EA[isnan(q_EA)] = 0
        q = qpre + q_fpre + q_lpre + q_EA
        Q = diags([q[:, 0]], [0])
        D = Cit.dot(Q).dot(C)
        mass = 0.5 * dt**2 * Ct2.dot(qpre + q_fpre + q_lpre + EA / linit)
        xyz0 = xyz.copy()
        # ----------------------------------------------------------------------
        # RK
        # ----------------------------------------------------------------------
        v0 = ca * v.copy()
        dv = rk2(a, v0, dt)
        v = v0 + dv
        dx = v * dt
        xyz[free] = xyz0[free] + dx[free]
        # update
        uvw = C.dot(xyz)
        l = normrow(uvw)
        f = q * l
        r = p - Ct.dot(Q).dot(uvw)
        # crits
        crit1 = norm(r[free])
        crit2 = norm(dx[free])
        # ufunc
        if ufunc:
            ufunc(k, crit1, crit2)
        # convergence
        if crit1 < tol1:
            break
        if crit2 < tol2:
            break
        print(k)
    return xyz, q, f, l, r
コード例 #11
0
def fn(dofs, *args):
    network, Xt, div, factor, tol, steps, ds = args
    X = update(dofs, network, Xt, div, factor, tol, steps, ds, refresh=0, bmesh=0, plot=0)
    ind = closest_points_points(X, Xt, distances=False)
    return 1000 * mean(normrow(X - Xt[ind, :]))
コード例 #12
0
edges = [(key_index[u], key_index[v]) for u, v in network.edges()]

C = connectivity_matrix(edges, rtype='list')
C = matlab.double(C)

# compute coordinate differences in Matlab

# # using an engine function
# uv = matlab.engine.mtimes(C, xyz)

# using workspace data
matlab.engine.workspace['C'] = C
matlab.engine.workspace['xyz'] = xyz

uv = matlab.engine.eval('C * xyz')

# compute edge lengths in Python

l = normrow(uv)
l = l.flatten().tolist()

# plot results as edge labels

plotter = NetworkPlotter(network)

plotter.draw_vertices()
plotter.draw_edges(text={(u, v): '%.1f' % l[index]
                         for index, (u, v) in enumerate(network.edges())})

plotter.show()