Source code for compas.numerical.fd.fd_numpy


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from numpy import asarray
from scipy.sparse import diags
from scipy.sparse.linalg import spsolve

from compas.numerical import connectivity_matrix
from compas.numerical import normrow


__all__ = ['fd_numpy']


[docs]def fd_numpy(vertices, edges, fixed, q, loads, **kwargs): """Implementation of the force density method to compute equilibrium of axial force networks. Parameters ---------- vertices : list XYZ coordinates of the vertices of the network edges : list Edges between vertices represented by fixed : list Indices of fixed vertices. q : list Force density of edges. loads : list XYZ components of the loads on the vertices. Returns ------- xyz : array XYZ coordinates of the equilibrium geometry. q : array Force densities in the edges. f : array Forces in the edges. l : array Lengths of the edges r : array Residual forces. Notes ----- For more info, see [1]_ References ---------- .. [1] Schek H., *The Force Density Method for Form Finding and Computation of General Networks*, Computer Methods in Applied Mechanics and Engineering 3: 115-134, 1974. Examples -------- >>> """ v = len(vertices) free = list(set(range(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)) # noqa: E741 f = q * l r = p - Ct.dot(Q).dot(C).dot(xyz) return xyz, q, f, l, r
# ============================================================================== # Main # ============================================================================== if __name__ == '__main__': import doctest doctest.testmod(globs=globals())