Beispiel #1
0
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()
Beispiel #2
0
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
Beispiel #3
0
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)
Beispiel #4
0
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
Beispiel #5
0
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)
Beispiel #6
0
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
Beispiel #7
0
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)
Beispiel #8
0
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)