def element_DsOF(el_nd_ids, doft): nn = len(el_nd_ids) nd = len(doft[0]) ix = zero_m((nn, nd), dtype=int) for i in xrange(nn): ix[i] = doft[el_nd_ids[i]] return ix.flatten()
def table_of_nodal_coordinates(cord, vertices, doft, ndc=None): if ndc is None: ndc = zero_m((doft.shape[0], cord.shape[1])) for i in xrange(doft.shape[0]): if doft[i, 0] == -1: ndc[i] = vertices[i] for i in xrange(doft.shape[0]): if doft[i, 0] != -1: ndc[i] = cord[doft[i, 0]] return ndc
def table_of_nodal_DsOF(v, fixed): dof_per_node = 1 dof_table = zero_m((v, dof_per_node), dtype=int) for s in fixed: dof_table[support_node_index(s)] = -1 ndof = 0 j = 0 for i in xrange(v): if dof_table[i, j] != -1: dof_table[i, j] = ndof ndof += 1 return (ndof, dof_table)
def _FDM_it(ndof, tdof, vertices, edges, q, lin_solver=cg, i_tol=1e-5, callbacks=no_callbacks): mD, mDf = mDmDf(ndof, tdof, vertices, edges, q) x0 = zero_m(mDf.shape) xyz = nodal_coordinates_it(mD, mDf, x0, vertices, tdof, lin_solver, i_tol, callbacks) return xyz
def multistepFDM_cg(vertices, edges, fixed, q, fcs=[], lcs=[], l0cs=[], steps=250, lin_solver=cg, i_tol=1e-5, callbacks=no_callbacks, cond_num=False): v = len(vertices) q0 = copy(q) ndof, tdof = table_of_nodal_DsOF(v, fixed) mD, mDf = mDmDf(ndof, tdof, vertices, edges, q0) if cond_num == True: print('01', ' max =', mD.max(), ' nrm1 =', sm_norm(inv(mD), 1), ' nrmF =', sm_norm(inv(mD)), ' cn =', cond(mD.A, 1)) x0 = zero_m(mDf.shape) cc = __solve_lin_syst_it(mD, -mDf, x0, lin_solver, i_tol, None, callbacks) xyz = table_of_nodal_coordinates(cc, vertices, tdof) l = list_of_element_lengths(edges, xyz) f = list_of_element_forces(l, q0) for i in xrange(2, steps + 1): for fj in fcs: q0[fj[0]] = fj[1] / l[fj[0]] for lj in lcs: q0[lj[0]] = f[lj[0]] / lj[1] for l0j in l0cs: i0 = l0j[0] l0 = l0j[1][0] ae0 = l0j[1][1] ffj = f[i0] ll = (ae0 + ffj) * l0 / ae0 q0[i0] = ffj / ll mD, mDf = mDmDf(ndof, tdof, vertices, edges, q0) if i % 10 == 1: print(i, ' max =', mD.max(), ' nrm1 =', sm_norm(inv(mD), 1), ' nrmF =', sm_norm(inv(mD)), ' cn =', cond(mD.A, 1)) cc = __solve_lin_syst_it(mD, -mDf, x0, lin_solver, i_tol, None, callbacks) xyz = table_of_nodal_coordinates(cc, vertices, tdof) l = list_of_element_lengths(edges, xyz) f = list_of_element_forces(l, q0) return (xyz, f, q0)
def mDmDf(ndof, doft, vertices, edges, q): ii = [] jj = [] aij = [] mDf = zero_m((ndof, 3)) for j in xrange(len(edges)): eni = edges[j] i0, i1 = element_DsOF(eni, doft) if i0 != -1: ii.append(i0) jj.append(i0) aij.append(q[j]) if i1 != -1: ii.append(i0) jj.append(i1) aij.append(-q[j]) else: nc = vertices[eni[1]] mDf[i0, 0] -= q[j] * nc[0] mDf[i0, 1] -= q[j] * nc[1] mDf[i0, 2] -= q[j] * nc[2] if i1 != -1: ii.append(i1) jj.append(i1) aij.append(q[j]) if i0 != -1: ii.append(i1) jj.append(i0) aij.append(-q[j]) else: nc = vertices[eni[0]] mDf[i1, 0] -= q[j] * nc[0] mDf[i1, 1] -= q[j] * nc[1] mDf[i1, 2] -= q[j] * nc[2] mD = csc_matrix((aij, (ii, jj)), shape=(ndof, ndof)) return mD, mDf
def multistepFDM_inexact(nodes, elems, supports, qs, fcs=[], lcs=[], l0cs=[], tol_f=1e-3, tol_l=1e-3, abs_error=True, lin_solver=cg, i_tol_min=None, i_tol_max=0.1, damping=1e-2, latest=True, steps=250, callbacks=no_callbacks): if abs_error == False: def force_diff(f, fs): df = [] for ff in fs: df.append(abs(f[ff[0]] - ff[1]) / ff[1]) return max(df) def length_diff(l, ls): dl = [] for ll in ls: dl.append(abs(l[ll[0]] - ll[1]) / ll[1]) return max(dl) def l0_diff(l, f, l0s): dl = [] for ll in l0s: i0 = ll[0] l0 = ll[1][0] ae0 = ll[1][1] dl.append(abs(unstrained_length(l[i0], f[i0], ae0) - l0) / l0) return max(dl) else: def force_diff(f, fs): df = [] for ff in fs: df.append(abs(f[ff[0]] - ff[1])) return max(df) def length_diff(l, ls): dl = [] for ll in ls: dl.append(abs(l[ll[0]] - ll[1])) return max(dl) def l0_diff(l, f, l0s): dl = [] for ll in l0s: i0 = ll[0] l0 = ll[1][0] ae0 = ll[1][1] dl.append(abs(unstrained_length(l[i0], f[i0], ae0) - l0)) return max(dl) qs0 = copy(qs) ndof, tdof = table_of_nodal_DsOF(len(nodes), supports) mD, mDf = mDmDf(ndof, tdof, nodes, elems, qs0) x0 = zero_m(mDf.shape) # nb1 = max (map (bind_2nd (v_norm, inf), mDf)) # nb1 = 1/nb1 if nb1 > 100 else 1e-2 # nb1 /= 2*sqrt (3.) nb = 5e-3 i_tol0 = i_tol_min if i_tol_min != None else min(tol_f, tol_l) * nb print('i_tol_min =', i_tol0) cc = __solve_lin_syst_it(mD, -mDf, x0, lin_solver, i_tol0, None, callbacks) nc = table_of_nodal_coordinates(cc, nodes, tdof) l = list_of_element_lengths(elems, nc) f = list_of_element_forces(l, qs0) rfd = rld = rl0d = 1e-13 if fcs != []: rfd1 = rfd rfd = force_diff(f, fcs) if lcs != []: rld1 = rld rld = length_diff(l, lcs) if l0cs != []: rl0d1 = rl0d rl0d = l0_diff(l, f, l0cs) print(1, i_tol0, rfd, rld, rl0d) if rfd < tol_f and rld < tol_l and rl0d < tol_l: print('steps:', 1) if fcs != []: print('maximal force error: ', rfd) if lcs != []: print('maximal length error: ', rld) if l0cs != []: print('maximal unstrained length error: ', rl0d) return (nc, f, qs0) i_tol1 = i_tol_max gamma_f = i_tol0 * (1 - sqrt(tol_f)) / tol_f**2 gamma_l = i_tol0 * (1 - sqrt(tol_l)) / tol_l**2 for i in xrange(2, steps + 1): if rfd >= tol_f: for fj in fcs: qs0[fj[0]] = fj[1] / l[fj[0]] if rld >= tol_l: for lj in lcs: qs0[lj[0]] = f[lj[0]] / lj[1] if rl0d >= tol_l: for l0j in l0cs: i0 = l0j[0] l0 = l0j[1][0] ae0 = l0j[1][1] ffj = f[i0] ll = (ae0 + ffj) * l0 / ae0 qs0[i0] = ffj / ll mD, mDf = mDmDf(ndof, tdof, nodes, elems, qs0) # nb1 = max (map (bind_2nd (v_norm, inf), -mDf)) # nb1 = 1/nb1 if nb1 > 100 else 1e-2 # nb1 /= 2*sqrt (3.) # i_tol0 = i_tol if i_tol != None else min (tol_f, tol_l) * nb x1 = cc if latest else x0 minrfd = minrld = minrl0d = 0.0 if fcs != []: minrfd = min(damping * rfd**3 / rfd1**2, gamma_f * rfd**2) if lcs != []: minrld = min(damping * rld**3 / rld1**2, gamma_l * rld**2) if l0cs != []: minrl0d = min(damping * rl0d**3 / rl0d1**2, gamma_l * rl0d**2) i_tol1 = min(i_tol_max, i_tol1, max(minrfd, minrld, minrl0d, i_tol0)) cc = __solve_lin_syst_it(mD, -mDf, x1, lin_solver, i_tol1, None, callbacks) # cc = __solve_lin_syst_it (mD, -mDf, x1, lin_solver, i_tol1, x1, callbacks) nc = table_of_nodal_coordinates(cc, nodes, tdof) # nc = table_of_nodal_coordinates (cc, nodes, tdof, nc) l = list_of_element_lengths(elems, nc) f = list_of_element_forces(l, qs0) if fcs != []: rfd1 = rfd rfd = force_diff(f, fcs) if lcs != []: rld1 = rld rld = length_diff(l, lcs) if l0cs != []: rl0d = l0_diff(l, f, l0cs) if i % 10 == 1: print(i, i_tol1, rfd, rld, rl0d) if rfd < tol_f and rld < tol_l and rl0d < tol_l: break if i == steps: print('WARNING: maximal number of steps (' + str(steps) + ') reached !') else: print('steps:', i) if fcs != []: print('maximal force error: ', rfd) if lcs != []: print('maximal length error: ', rld) if l0cs != []: print('maximal unstrained length error: ', rl0d) return (nc, f, qs0)
def multistepFDM_wtol_cg(vertices, edges, fixed, q, fcs=[], lcs=[], l0cs=[], tol_f=1e-3, tol_l=1e-3, abs_error=True, lin_solver=cg, i_tol=None, latest=True, steps=250, callbacks=no_callbacks): if abs_error == False: def force_diff(f, fs): df = [] for ff in fs: df.append(abs(f[ff[0]] - ff[1]) / ff[1]) return max(df) def length_diff(l, ls): dl = [] for ll in ls: dl.append(abs(l[ll[0]] - ll[1]) / ll[1]) return max(dl) def l0_diff(l, f, l0s): dl = [] for ll in l0s: i0 = ll[0] l0 = ll[1][0] ae0 = ll[1][1] dl.append(abs(unstrained_length(l[i0], f[i0], ae0) - l0) / l0) return max(dl) else: def force_diff(f, fs): df = [] for ff in fs: df.append(abs(f[ff[0]] - ff[1])) return max(df) def length_diff(l, ls): dl = [] for ll in ls: dl.append(abs(l[ll[0]] - ll[1])) return max(dl) def l0_diff(l, f, l0s): dl = [] for ll in l0s: i0 = ll[0] l0 = ll[1][0] ae0 = ll[1][1] dl.append(abs(unstrained_length(l[i0], f[i0], ae0) - l0)) return max(dl) q0 = copy(q) v = len(vertices) ndof, tdof = table_of_nodal_DsOF(v, fixed) mD, mDf = mDmDf(ndof, tdof, vertices, edges, q0) x0 = zero_m(mDf.shape) nb = 5e-3 i_tol = i_tol if i_tol != None else min(tol_f, tol_l) * nb print('i_tol =', i_tol) cc = __solve_lin_syst_it(mD, -mDf, x0, lin_solver, i_tol, None, callbacks) xyz = table_of_nodal_coordinates(cc, vertices, tdof) l = list_of_element_lengths(edges, xyz) f = list_of_element_forces(l, q0) rfd = rld = rl0d = 0 if fcs != []: rfd = force_diff(f, fcs) if lcs != []: rld = length_diff(l, lcs) if l0cs != []: rl0d = l0_diff(l, f, l0cs) print(1, rfd, rld) if rfd < tol_f and rld < tol_l and rl0d < tol_l: print('steps:', 1) if fcs != []: print('maximal force error: ', rfd) if lcs != []: print('maximal length error: ', rld) if l0cs != []: print('maximal unstrained length error: ', rl0d) return (xyz, f, q0) for i in xrange(2, steps + 1): if rfd >= tol_f: for fj in fcs: q0[fj[0]] = fj[1] / l[fj[0]] if rld >= tol_l: for lj in lcs: q0[lj[0]] = f[lj[0]] / lj[1] if rl0d >= tol_l: for l0j in l0cs: i0 = l0j[0] l0 = l0j[1][0] ae0 = l0j[1][1] ffj = f[i0] ll = (ae0 + ffj) * l0 / ae0 q0[i0] = ffj / ll mD, mDf = mDmDf(ndof, tdof, vertices, edges, q0) x1 = cc if latest else x0 cc = __solve_lin_syst_it(mD, -mDf, x1, lin_solver, i_tol, None, callbacks) xyz = table_of_nodal_coordinates(cc, vertices, tdof) l = list_of_element_lengths(edges, xyz) f = list_of_element_forces(l, q0) if fcs != []: rfd = force_diff(f, fcs) if lcs != []: rld = length_diff(l, lcs) if l0cs != []: rl0d = l0_diff(l, f, l0cs) if i % 10 == 1: print(i, rfd, rld) if rfd < tol_f and rld < tol_l and rl0d < tol_l: break if i == steps: print('WARNING: maximal number of steps (' + str(steps) + ') reached !') else: print('steps:', i) if fcs != []: print('maximal force error: ', rfd) if lcs != []: print('maximal length error: ', rld) if l0cs != []: print('maximal unstrained length error: ', rl0d) return (xyz, f, q0)