def drx_numba(network, factor=1.0, tol=0.1, steps=10000, summary=0, update=False): """ Run Numba accelerated dynamic relaxation analysis. Parameters ---------- network : obj Network to analyse. factor : float Convergence factor. tol : float Tolerance value. steps : int Maximum number of steps. summary : int Print summary at end (1:yes or 0:no). update : bool Update the co-ordinates of the Network. Returns ------- array Vertex co-ordinates. array Edge forces. array Edge lengths. """ # Setup tic1 = time() args = _args(network, factor, summary, steps, tol) toc1 = time() - tic1 # Solver tic2 = time() tol, steps, summary, m, n, u, v, X, f0, l0, k0, ind_c, ind_t, B, P, S, rows, cols, vals, nv, M, factor, V, inds, indi, indf, EIx, EIy, beams, C = args drx_solver_numba(tol, steps, summary, m, n, u, v, X, f0, l0, k0, ind_c, ind_t, B, P, S, rows, cols, vals, nv, M, factor, V, inds, indi, indf, EIx, EIy, beams) _, l = uvw_lengths(C, X) # noqa: E741 f = f0 + k0 * (l.ravel() - l0) toc2 = time() - tic2 # Summary if summary: print('\n\nNumba DR -------------------') print('Setup time: {0:.3f} s'.format(toc1)) print('Solver time: {0:.3f} s'.format(toc2)) print('----------------------------------') # Update if update: k_i = network.key_index() uv_i = network.uv_index() for key in network.vertices(): x, y, z = X[k_i[key], :] network.set_vertex_attributes(key, 'xyz', [x, y, z]) for uv in network.edges(): i = uv_i[uv] network.set_edge_attribute(uv, 'f', float(f[i])) return X, f, l
def drx_solver_numpy(tol, steps, factor, C, Ct, X, M, k0, l0, f0, ind_c, ind_t, P, S, B, V, refresh, beams, inds, indi, indf, EIx, EIy, callback, **kwargs): """ NumPy and SciPy dynamic relaxation solver. Parameters ---------- tol : float Tolerance value. steps : int Maximum number of steps. factor : float Convergence factor. C : array Connectivity matrix. Ct : array Transposed connectivity matrix. X : array Nodal co-ordinates. M : array Mass matrix. k0 : array Initial edge axial stiffnesses. l0 : array Initial edge lengths. f0 : array Initial edge forces. ind_c : list Indices of compression only edges. ind_t : list Indices of tension only edges. P : array Nodal loads Px, Py, Pz. S : array Shear forces Sx, Sy, Sz. B : array Constraint conditions Bx, By, Bz. V : array Nodal velocities Vx, Vy, Vz. refresh : int Update progress every n steps. beams : int Beam data flag 1 or 0. inds : array Indices of beam element start nodes. indi : array Indices of beam element intermediate nodes. indf : array Indices of beam element finish nodes beams. EIx : array Nodal EIx flexural stiffnesses. EIy : array Nodal EIy flexural stiffnesses. callback : obj Callback function. Returns ------- array Vertex co-ordinates. array Edge forces. array Edge lengths. """ res = 1000 * tol ts, Uo = 0, 0 M = factor * tile(M.reshape((-1, 1)), (1, 3)) while (ts <= steps) and (res > tol): uvw, l = uvw_lengths(C, X) f = f0 + k0 * (l.ravel() - 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[:, newaxis] / 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: if (ts % refresh == 0) or (res < tol): print('Step:{0} Residual:{1:.3f}'.format(ts, res)) if callback: callback(X, **kwargs) ts += 1 return X, f, l
def drx_solver(tol, steps, factor, C, Ct, X, ks, l0, f0, ind_c, ind_t, P, S, B, M, V, refresh, beams, inds, indi, indf, EIx, EIy, callback, **kwargs): """ NumPy and SciPy dynamic relaxation solver. Parameters: tol (float): Tolerance limit. steps (int): Maximum number of 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): Indices of compression only edges. ind_t (list): Indices of 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. V (array): Nodal velocities Vx, Vy, Vz. refresh (int): Update progress every n steps. 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. callback (obj): Callback function. Returns: array: Updated nodal co-ordinates. array: Updated forces. array: Updated 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 = 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: if (ts % refresh == 0) or (res < tol): print('Step:{0} Residual:{1:.3g}'.format(ts, res)) if callback: callback(X, **kwargs) ts += 1 return X, f, l
def drx_numba(network, factor=1.0, tol=0.1, steps=10000, summary=0, update=False): """ Run Numba accelerated dynamic relaxation analysis. Parameters ---------- network (obj): Network to analyse. factor (float): Convergence factor. tol (float): Tolerance value. steps (int): Maximum number of steps. summary (int): Print summary at end. update (bool): Update the co-ordinates of the Network. Returns ------- array: Vertex co-ordinates. array: Edge forces. array: Edge lengths. """ # Setup tic1 = time() X, B, P, Pn, S, V, E, A, C, Ct, f0, l0, ind_c, ind_t, u, v, M, ks = _create_arrays( network) try: inds, indi, indf, EIx, EIy = _beam_data(network) inds = array(inds) indi = array(indi) indf = array(indf) EIx = EIx.ravel() EIy = EIy.ravel() beams = 1 except AttributeError: z0, z1 = array([0]), array([0.]) inds, indi, indf, EIx, EIy = z0, z0, z0, z1, z1 beams = 0 # Arrays f0_ = f0.ravel() ks_ = ks.ravel() l0_ = l0.ravel() M_ = M.ravel() if not ind_c: ind_c = [-1] if not ind_t: ind_t = [-1] ind_c = array(ind_c) ind_t = array(ind_t) rows, cols, vals = find(Ct) toc1 = time() - tic1 # Solver tic2 = time() X = drx_solver(tol, steps, factor, u, v, X, ks_, l0_, f0_, ind_c, ind_t, rows, cols, vals, P, S, B, M_, summary, inds, indi, indf, EIx, EIy, beams) _, l = uvw_lengths(C, X) f = f0 + ks * (l - l0) toc2 = time() - tic2 # Summary if summary: print('\n\nNumba DR -------------------') print('Setup time: {0:.3g}s'.format(toc1)) print('Solver time: {0:.3g}s'.format(toc2)) print('----------------------------------') # Update if update: i_k = network.index_key() for i in sorted(list(network.vertices()), key=int): x, y, z = X[i, :] network.set_vertex_attributes(i_k[i], {'x': x, 'y': y, 'z': z}) uv_i = network.uv_index() for edge in network.edges(): i = uv_i[edge] network.set_edge_attribute(edge, 'f', float(f[i])) return X, f, l