def test_structured_grid(vol_corr=True):
    m = RectangleMesh(Point(0,0), Point(2,1), 20, 10)
    struct_grd = True
    vol_corr = True

    """hard coded bcs"""
    bc_loc = [0,1]
    bc_type = {'dirichlet':0, 'forceY':1}
    bc_vals = {'dirichlet':0, 'forceY':-5e8}
    num_lyrs = 2 #num layers of cells for BC

    cell_cent, cell_vol = add_ghost_cells(m, bc_loc, num_lyrs, struct_grd)
    el = get_peridym_edge_length(cell_cent, struct_grd)
    extents = compute_modified_extents(cell_cent, el, struct_grd)
    dim = np.shape(cell_cent[0])[0]
    
    #boundary conditions managment
    node_ids_dir = get_boundary_layers(cell_cent, el, num_lyrs, bc_loc, struct_grd)
    node_ids_frc = get_boundary_layers(cell_cent, el, 2*num_lyrs, bc_loc, struct_grd)
    ghost_lyr_node_ids = node_ids_dir

    omega_fun = gaussian_infl_fun1
    E, nu, rho, mu, bulk, gamma = get_steel_properties(dim)
    
    horizon = 2.001*np.abs(np.diff(cell_cent[0:2][:,0])[0])
    tree = QuadTree()
    tree.put(extents, horizon)
    
    nbr_lst, nbr_beta_lst = tree_nbr_search(tree.get_linear_tree(), cell_cent, horizon, vol_corr, struct_grd)
    mw = peridym_compute_weighted_volume(cell_cent, cell_vol, nbr_lst,nbr_beta_lst, horizon, omega_fun)
    
    K = computeK(horizon, cell_vol, nbr_lst, nbr_beta_lst, mw, cell_cent, E, nu, mu, bulk, gamma, omega_fun)
    
    K_bound, fb = peridym_apply_bc(K, bc_type, bc_vals, cell_cent, cell_vol, node_ids_dir, node_ids_frc, struct_grd)
    u_disp = direct_solver(K_bound, fb, dim, reshape=True) 
    cell_cent_orig, u_disp_orig, u_disp_ghost = recover_original_peridynamic_mesh(cell_cent, u_disp, bc_type, ghost_lyr_node_ids, struct_grd)
    disp_cent = get_displaced_soln(cell_cent_orig, u_disp_orig, horizon, dim, plot_=True, zoom=10)
    
    return K, disp_cent
Example #2
0
def solve_peridynamic_bar_axial(horizon, m=mesh, nbr_lst=None, nbr_beta_lst=None, material='steel', omega_fun=None, plot_=False, force=25e9, vol_corr=True, struct_grd=False, response='LPS'):
    """
    solves the peridynamic bar with a specified load

    """
    if response == 'LPS':
        computeStiffness = computeK
    if response == 'correspondance':
        computeStiffness = computeKCorrespondance
    

    dmg_flag=False
    print('horizon value: %4.3f\n'%horizon)

    
    bc_type = {'dirichlet':0, 'forceX':1}
    bc_vals = {'dirichlet': 0, 'forceX': force}
    bc_loc = [0,1]
    num_lyrs = 3 #three times discretization width
    cell_cent, cell_vol = add_ghost_cells(m, bc_loc, num_lyrs, struct_grd) 
    el = get_peridym_edge_length(cell_cent, struct_grd)
    extents = compute_modified_extents(cell_cent, el, struct_grd)
    dim = m.topology().dim() 
     
    
    #boudary conditions management
    node_ids_dir = get_boundary_layers(cell_cent, el, num_lyrs, bc_loc, struct_grd)
    node_ids_frc = get_boundary_layers(cell_cent, el, 2*num_lyrs, bc_loc, struct_grd)
    ghost_lyr_node_ids = node_ids_dir

    if material is 'steel':
        E, nu, rho, mu, bulk, gamma = get_steel_properties(dim)

    if (nbr_lst==None or nbr_beta_lst==None):
        tree = QuadTree()
        tree.put(extents, horizon)
        nbr_lst, nbr_beta_lst = tree_nbr_search(tree.get_linear_tree(), cell_cent, horizon, vol_corr, struct_grd)
    
    ## Initialize simulation
    G0 = 1000000/2
    s0 = compute_critical_stretch(G0, bulk, horizon)
    u_disp = np.zeros((len(cell_cent), dim), dtype=float)
    bnd_dmg_lst = compute_bond_damage(s0, cell_cent, nbr_lst, u_disp, dmg_flag)

    mw = peridym_compute_weighted_volume(cell_cent, cell_vol, nbr_lst, nbr_beta_lst, horizon, omega_fun) 
    K = computeStiffness(horizon, cell_vol, nbr_lst, nbr_beta_lst, bnd_dmg_lst, mw, cell_cent, E, nu, mu, bulk, gamma, omega_fun, u_disp)   
    #apply bc
    K_bound, fb = peridym_apply_bc(K, bc_type, bc_vals, cell_cent, cell_vol, node_ids_dir, node_ids_frc, struct_grd)
    #solve
    u_disp = direct_solver(K_bound, fb, dim, reshape=True)
   
    cell_cent_orig, u_disp_orig, _ = recover_original_peridynamic_mesh(cell_cent, u_disp, bc_type, ghost_lyr_node_ids, struct_grd)
    #disp_cent = u_disp + cell_cent
    
    disp_cent = get_displaced_soln(cell_cent_orig, u_disp_orig, horizon, dim, plot_=False, zoom=10)
    
    if plot_:
        import matplotlib.patches as patches
        bndR = np.ravel((np.argwhere(cell_cent_orig[:,0] == np.max(cell_cent_orig[:,0]))))
        bndL = np.ravel((np.argwhere(cell_cent_orig[:,0] == np.min(cell_cent_orig[:,0]))))
        bndB = np.ravel((np.argwhere(cell_cent_orig[:,1] == np.min(cell_cent_orig[:,1]))))
        bndT = np.ravel((np.argwhere(cell_cent_orig[:,1] == np.max(cell_cent_orig[:,1]))))
        x_r, y_r = cell_cent_orig[bndR].T
        x_l, y_l = cell_cent_orig[bndL].T
        x_b, y_b = cell_cent_orig[bndB].T
        x_t, y_t = cell_cent_orig[bndT].T
        
        fig = plt.figure()
        ax = fig.add_subplot(111)
        X,Y = disp_cent.T
        plt.scatter(X,Y,marker='o', s=100, color='b', alpha=0.5)
        #plt.scatter(x_r,y_r, marker='o', s=100, color='k', alpha=0.25)
        #plt.scatter(x_l,y_l, marker='o', s=100, color='k', alpha=0.25)
        #plt.scatter(x_b,y_b, marker='o', s=100, color='k', alpha=0.25)
        #plt.scatter(x_t,y_t, marker='o', s=100, color='k', alpha=0.25)
        #plt.title('axial load, force = %4.2g, vol corr= %s'%(force, str(vol_corr)))
        ax.add_patch(patches.Rectangle((0, 0), 2, 1, fill=False, color='k', linewidth=2.0, alpha=1))
        ax.set_aspect('equal')
        plt.show(block=False)
    
    return K, K_bound, disp_cent, u_disp_orig
def solve_peridynamic_bar_transverse(horizon,
                                     m=mesh,
                                     nbr_lst=None,
                                     nbr_beta_lst=None,
                                     material='steel',
                                     omega_fun=None,
                                     plot_=False,
                                     force=-5e8,
                                     vol_corr=True,
                                     struct_grd=False,
                                     response='LPS'):
    """
    solves the peridynamic bar with a specified load

    """
    print(
        '********** SOLVING PERIDYNAMIC TRANSVERSE TRACTION LOAD PROBLEM ***********'
    )
    if response == 'LPS':
        computeStiffness = computeK
    if response == 'correspondance':
        computeStiffness = computeKCorrespondance

    dmg_flag = False
    print('horizon value: %4.3f\n' % horizon)

    bc_type = {'dirichlet': 0, 'forceY': 1}
    bc_vals = {'dirichlet': 0, 'forceY': force}
    bc_loc = [0, 1]
    num_lyrs = 3  #three times discretization width
    cell_cent, cell_vol = add_ghost_cells(m, bc_loc, num_lyrs, struct_grd)
    el = get_peridym_edge_length(cell_cent, struct_grd)
    extents = compute_modified_extents(cell_cent, el, struct_grd)
    dim = m.topology().dim()

    #boudary conditions management
    node_ids_dir = get_boundary_layers(cell_cent, el, num_lyrs, bc_loc,
                                       struct_grd)
    node_ids_frc = get_boundary_layers(cell_cent, el, 2 * num_lyrs, bc_loc,
                                       struct_grd)
    ghost_lyr_node_ids = node_ids_dir

    if material is 'steel':
        E, nu, rho, mu, bulk, gamma = get_steel_properties(dim)

    if (nbr_lst == None or nbr_beta_lst == None):
        tree = QuadTree()
        tree.put(extents, horizon)
        nbr_lst, nbr_beta_lst = tree_nbr_search(tree.get_linear_tree(),
                                                cell_cent, horizon, vol_corr,
                                                struct_grd)

    ## Initialize simulation
    G0 = 1000000 / 2
    s0 = compute_critical_stretch(G0, bulk, horizon)
    u_disp = np.zeros((len(cell_cent), dim), dtype=float)
    bnd_dmg_lst = compute_bond_damage(s0, cell_cent, nbr_lst, u_disp, dmg_flag)

    mw = peridym_compute_weighted_volume(cell_cent, cell_vol, nbr_lst,
                                         nbr_beta_lst, horizon, omega_fun)
    K = computeStiffness(horizon, cell_vol, nbr_lst, nbr_beta_lst, bnd_dmg_lst,
                         mw, cell_cent, E, nu, mu, bulk, gamma, omega_fun,
                         u_disp)
    #apply bc
    K_bound, fb = peridym_apply_bc(K, bc_type, bc_vals, cell_cent, cell_vol,
                                   node_ids_dir, node_ids_frc, struct_grd)
    #solve
    u_disp = direct_solver(K_bound, fb, dim, reshape=True)

    cell_cent_orig, u_disp_orig, _ = recover_original_peridynamic_mesh(
        cell_cent, u_disp, bc_type, ghost_lyr_node_ids, struct_grd)
    #disp_cent = u_disp + cell_cent

    disp_cent = get_displaced_soln(cell_cent_orig,
                                   u_disp_orig,
                                   horizon,
                                   dim,
                                   plot_=plot_,
                                   zoom=10)

    return K, K_bound, disp_cent, u_disp_orig
nbr_lst, nbr_beta_lst = tree_nbr_search(tree.get_linear_tree(), cell_cent,
                                        horizon, vol_corr, struct_grd)
mw = peridym_compute_weighted_volume(cell_cent, cell_vol, nbr_lst,
                                     nbr_beta_lst, horizon, omega_fun)

#initialize
u_disp = np.zeros((len(cell_cent), dim), dtype=float)
bnd_dmg_lst = compute_bond_damage(s0, cell_cent, nbr_lst, u_disp)

#K = computeK(horizon, cell_vol, nbr_lst, nbr_beta_lst, bnd_dmg_lst, mw, cell_cent, E, nu, mu, bulk, gamma, omega_fun, u_disp)
K = computeKCorrespondance(horizon, cell_vol, nbr_lst, nbr_beta_lst,
                           bnd_dmg_lst, mw, cell_cent, E, nu, mu, bulk, gamma,
                           omega_fun, u_disp)
K_bound, fb = peridym_apply_bc(K, bc_type, bc_vals, cell_cent, cell_vol,
                               node_ids_dirichlet, node_ids_force, struct_grd)

u_disp = direct_solver(K_bound, fb, dim, reshape=True)

cell_cent_orig, u_disp_orig, u_disp_ghost = recover_original_peridynamic_mesh(
    cell_cent, u_disp, bc_type, ghost_lyr_node_ids, struct_grd)
K_orig = recover_stiffness_for_original_mesh(K, cell_cent, bc_type,
                                             ghost_lyr_node_ids, struct_grd)

u_disp_flat = np.zeros(len(cell_cent_orig) * dim, dtype=float)
disp_cent = get_displaced_soln(cell_cent_orig,
                               u_disp_orig,
                               horizon,
                               dim,
                               plot_=True,
                               zoom=20)
Example #5
0
def solve_peridynamic_patch_test(horizon,
                                 u_fe_conv=None,
                                 m=mesh,
                                 nbr_lst=None,
                                 nbr_beta_lst=None,
                                 material='steel',
                                 omega_fun=None,
                                 plot_=True,
                                 force=75e9,
                                 vol_corr=True,
                                 struct_grd=True,
                                 response='LPS'):
    """
    solves the peridynamic bar with a specified load

    """
    print('********** SOLVING PERIDYNAMIC PATCH TEST LOAD PROBLEM ***********')
    if response == 'LPS':
        computeStiffness = computeK
    if response == 'correspondance':
        computeStiffness = computeKCorrespondance

    dmg_flag = False
    print('horizon value: %4.3f\n' % horizon)

    bc_type = {'dirichletX': 0, 'forceX': 1}
    bc_vals = {'dirichletX': 0, 'forceX': force}
    bc_loc = [0, 1]
    num_lyrs = 3  #three times discretization width
    cell_cent, cell_vol = add_ghost_cells(m, bc_loc, num_lyrs, struct_grd)
    el = get_peridym_edge_length(cell_cent, struct_grd)
    extents = compute_modified_extents(cell_cent, el, struct_grd)
    dim = m.topology().dim()

    #boudary conditions management
    node_ids_dir = get_boundary_layers(cell_cent, el, num_lyrs, bc_loc,
                                       struct_grd)
    node_ids_frc = get_boundary_layers(cell_cent, el, 2 * num_lyrs, bc_loc,
                                       struct_grd)
    ghost_lyr_node_ids = node_ids_dir

    if material is 'steel':
        E, nu, rho, mu, bulk, gamma = get_steel_properties(dim)

    if (nbr_lst == None or nbr_beta_lst == None):
        tree = QuadTree()
        tree.put(extents, horizon)
        nbr_lst, nbr_beta_lst = tree_nbr_search(tree.get_linear_tree(),
                                                cell_cent, horizon, vol_corr,
                                                struct_grd)

    ## Initialize simulation
    G0 = 1000000 / 2
    s0 = compute_critical_stretch(G0, bulk, horizon)
    u_disp = np.zeros((len(cell_cent), dim), dtype=float)
    bnd_dmg_lst = compute_bond_damage(s0, cell_cent, nbr_lst, u_disp, dmg_flag)

    mw = peridym_compute_weighted_volume(cell_cent, cell_vol, nbr_lst,
                                         nbr_beta_lst, horizon, omega_fun)
    K = computeStiffness(horizon, cell_vol, nbr_lst, nbr_beta_lst, bnd_dmg_lst,
                         mw, cell_cent, E, nu, mu, bulk, gamma, omega_fun,
                         u_disp)
    #apply bc
    K_bound, fb = peridym_apply_bc(K, bc_type, bc_vals, cell_cent, cell_vol,
                                   node_ids_dir, node_ids_frc, struct_grd)

    #fix the lower corners of dirichlet node ids manually :(
    fixed_nodes = node_ids_dir[bc_type['dirichletX']][0][0:num_lyrs]
    for nk in fixed_nodes:
        K_bound[nk * dim + 0] = 0.0
        K_bound[nk * dim + 1] = 0.0
        K_bound[nk * dim + 0][nk * dim + 0] = 1.0
        K_bound[nk * dim + 1][nk * dim + 1] = 1.0
        fb[nk * dim + 0] = 0.0
        fb[nk * dim + 1] = 0.0
    #solve
    u_disp = direct_solver(K_bound, fb, dim, reshape=True)

    cell_cent_orig, u_disp_orig, _ = recover_original_peridynamic_mesh(
        cell_cent, u_disp, bc_type, ghost_lyr_node_ids, struct_grd)
    #disp_cent = u_disp + cell_cent

    disp_cent = get_displaced_soln(cell_cent_orig,
                                   u_disp_orig,
                                   horizon,
                                   dim,
                                   plot_=plot_,
                                   zoom=20)
    if u_fe_conv == None:
        return K, K_bound, disp_cent, u_disp_orig
    else:
        #get right end cells
        boundElIds = np.ravel(
            (np.argwhere(cell_cent_orig[:, 0] == np.max(cell_cent_orig[:,
                                                                       0]))))
        cell_cent_right = cell_cent_orig[boundElIds]
        u_fe_conv_right_end = np.zeros((len(boundElIds), 2), dtype=float)

        for i, cc in enumerate(cell_cent_right):
            u_fe_conv_right_end[i] = u_fe_conv(cc)

        u_x_disp_PD_right = u_disp_orig[boundElIds][:, 0]
        u_x_disp_FE_right = u_fe_conv_right_end[:, 0]

        avg_x_disp_PD = np.average(u_x_disp_PD_right)
        avg_x_disp_FE = np.average(u_x_disp_FE_right)

        abs_err_avg_x_disp = abs(avg_x_disp_PD - avg_x_disp_FE)
        rel_err_avg_x_disp = abs_err_avg_x_disp / avg_x_disp_FE * 100.0

        bndL = np.ravel(
            (np.argwhere(cell_cent_orig[:, 0] == np.min(cell_cent_orig[:,
                                                                       0]))))
        bndB = np.ravel(
            (np.argwhere(cell_cent_orig[:, 1] == np.min(cell_cent_orig[:,
                                                                       1]))))
        bndT = np.ravel(
            (np.argwhere(cell_cent_orig[:, 1] == np.max(cell_cent_orig[:,
                                                                       1]))))
        x_r, y_r = cell_cent_right.T
        x_l, y_l = cell_cent_orig[bndL].T
        x_b, y_b = cell_cent_orig[bndB].T
        x_t, y_t = cell_cent_orig[bndT].T

        fig = plt.figure()
        ax = fig.add_subplot(111)
        X, Y = disp_cent.T
        plt.scatter(X, Y, marker='o', s=100, color='b', alpha=0.5)
        plt.scatter(x_r, y_r, marker='o', s=100, color='g', alpha=0.7)
        plt.scatter(x_l, y_l, marker='o', s=100, color='g', alpha=0.7)
        plt.scatter(x_b, y_b, marker='o', s=100, color='g', alpha=0.7)
        plt.scatter(x_t, y_t, marker='o', s=100, color='g', alpha=0.7)
        import matplotlib.patches as patches
        ax.add_patch(
            patches.Rectangle((0, 0),
                              2,
                              1,
                              fill=False,
                              color='k',
                              linewidth=2.0,
                              alpha=1))
        ax.set_aspect('equal')
        plt.show(block=False)
        return disp_cent, u_x_disp_PD_right, u_x_disp_FE_right, avg_x_disp_PD, avg_x_disp_FE, abs_err_avg_x_disp, rel_err_avg_x_disp
Example #6
0
def run_correspondance_tests():
    """TODO: Docstring for run_correspondance_tests.
    :returns: TODO

    """
    unstr_msh_lst, strct_msh_lst = generate_struct_mesh_list_for_pd_tests()

    dim = 2
    struct_grd = True
    vol_corr = False
    bc_type = {'dirichlet': 0, 'forceX': 1}
    bc_vals = {'dirichlet': 0, 'forceX': 10e8}
    bc_loc = [0, 1]
    num_lyrs = 2  #num of additional layers on boundary
    E, nu, rho, mu, bulk, gamma = get_steel_properties(dim)

    horizon_ratio = np.arange(2.0001, 6.0001, 1.)
    G0 = 1000000 / 2

    for m in strct_msh_lst[3:4]:
        cell_cent, cell_vol = add_ghost_cells(m, bc_loc, num_lyrs, struct_grd)
        el = get_peridym_edge_length(cell_cent, struct_grd)
        extents = compute_modified_extents(cell_cent, el, struct_grd)

        node_ids_dirichlet = get_boundary_layers(cell_cent, el, num_lyrs,
                                                 bc_loc, struct_grd)
        node_ids_force = get_boundary_layers(cell_cent, el, 2 * num_lyrs,
                                             bc_loc, struct_grd)
        ghost_lyr_node_ids = node_ids_dirichlet

        node_cents_dirichlet = get_bound_cell_cents(node_ids_dirichlet,
                                                    cell_cent)
        node_cents_force = get_bound_cell_cents(node_ids_force, cell_cent)
        omega_fun = gaussian_infl_fun2

        for ratio in horizon_ratio:

            horizon = ratio * np.abs(np.diff(cell_cent[0:2][:, 0])[0])
            print("testing with mesh size : %i and horizon size %4.2g" %
                  (int(m.num_cells() * 0.5), horizon))
            s0 = compute_critical_stretch(G0, bulk, horizon)
            tree = QuadTree()
            tree.put(extents, horizon)

            nbr_lst, nbr_beta_lst = tree_nbr_search(tree.get_linear_tree(),
                                                    cell_cent, horizon,
                                                    vol_corr, struct_grd)
            mw = peridym_compute_weighted_volume(cell_cent, cell_vol, nbr_lst,
                                                 nbr_beta_lst, horizon,
                                                 omega_fun)

            #initialize
            u_disp = np.zeros((len(cell_cent), dim), dtype=float)
            bnd_dmg_lst = compute_bond_damage(s0, cell_cent, nbr_lst, u_disp)

            #K = computeK(horizon, cell_vol, nbr_lst, nbr_beta_lst, bnd_dmg_lst, mw, cell_cent, E, nu, mu, bulk, gamma, omega_fun, u_disp)
            K = computeKCorrespondance(horizon, cell_vol, nbr_lst,
                                       nbr_beta_lst, bnd_dmg_lst, mw,
                                       cell_cent, E, nu, mu, bulk, gamma,
                                       omega_fun, u_disp)
            K_bound, fb = peridym_apply_bc(K, bc_type, bc_vals, cell_cent,
                                           cell_vol, node_ids_dirichlet,
                                           node_ids_force, struct_grd)

            u_disp = direct_solver(K_bound, fb, dim, reshape=True)

            cell_cent_orig, u_disp_orig, u_disp_ghost = recover_original_peridynamic_mesh(
                cell_cent, u_disp, bc_type, ghost_lyr_node_ids, struct_grd)
            K_orig = recover_stiffness_for_original_mesh(
                K, cell_cent, bc_type, ghost_lyr_node_ids, struct_grd)

            zoom = 20
            disp_cent = cell_cent_orig + zoom * u_disp_orig

            fig = plt.figure()
            ax = fig.add_subplot(111)
            X, Y = disp_cent.T
            plt.scatter(X, Y, marker='o', s=150, color='b', alpha=0.6)
            plt.xlim(-0.05, 2.12)
            plt.ylim(-0.26, 1.05)
            ax.set_aspect('equal')
            plt.title(r'$N=%i, \Delta x=%4.3g , \delta=%4.0f\Delta x$' %
                      (len(cell_cent_orig), el[0], ratio),
                      fontsize=14)
            plt.show(block=False)
Example #7
0
def run_fracture_test():
    #m = box_mesh(Point(0,0,0), Point(2,1,1), 10,5,5)
    #m = box_mesh_with_hole(numpts=20)
    #domain = mshr.Rectangle(Point(0,0), Point(3,1))
    #m = mshr.generate_mesh(domain, 30)
    m = RectangleMesh(Point(0, 0), Point(2, 1), 30, 15)
    #m = rectangle_mesh(numptsX=20, numptsY=10)
    #m = rectangle_mesh_with_hole(npts=25)

    struct_grd = True
    vol_corr = True
    dmg_flag = True
    save_fig = True
    pplot = False

    f0 = 10e8
    delta_t = 0.00025
    ft = 50e9
    t = 0.0

    bc_type = {'dirichlet': 0, 'forceX': 1}
    bc_vals = {'dirichlet': 0, 'forceX': 0}
    bc_loc = [0, 1]
    num_lyrs = 2  #num of additional layers on boundary
    cell_cent, cell_vol = add_ghost_cells(m, bc_loc, num_lyrs, struct_grd)
    dim = np.shape(cell_cent[0])[0]
    el = get_peridym_edge_length(cell_cent, struct_grd)

    # dirichlet bc on ghost layers
    node_ids_dir = get_boundary_layers(cell_cent, el, 3, bc_loc, struct_grd)
    node_ids_frc = get_boundary_layers(cell_cent, el, 2 * num_lyrs, bc_loc,
                                       struct_grd)
    ghost_lyr_node_ids = node_ids_dir

    omega_fun = gaussian_infl_fun2
    E, nu, rho, mu, bulk, gamma = get_steel_properties(dim)

    horizon = 3.001 * np.abs(np.diff(cell_cent[0:2][:, 0])[0])

    num_steps = 500
    u_disp = np.zeros((len(cell_cent), dim), dtype=float)

    G0 = 1000000 / 2
    s0 = s0 = compute_critical_stretch(G0, bulk, horizon)

    if save_fig:
        pwd = getcwd()
        today = dttm.now().strftime("%Y%m%d%%H%M%S")
        data_dir_top = path.join(pwd, today)
        mkdir(data_dir_top)
    else:
        data_dir_top = None

    for i in range(num_steps):

        print("********************************************")
        print("********************************************")
        print("START : time step %i" % i)

        t = (i + 1) * delta_t
        force = f0 + ft * i * delta_t + 0.10 * ft * t**2
        print("appyling external body force: %.4g" % force)

        bc_vals['forceX'] = force
        extents = compute_modified_extents(cell_cent, el, struct_grd)

        tree = QuadTree()
        tree.put(extents, horizon)

        nbr_lst, nbr_beta_lst = tree_nbr_search(tree.get_linear_tree(),
                                                cell_cent, horizon, vol_corr,
                                                struct_grd)
        bnd_dmg_lst = compute_bond_damage(s0, cell_cent, nbr_lst, u_disp,
                                          dmg_flag)
        mw = peridym_compute_weighted_volume(cell_cent, cell_vol, nbr_lst,
                                             nbr_beta_lst, horizon, omega_fun)

        K = computeK(horizon, cell_vol, nbr_lst, nbr_beta_lst, bnd_dmg_lst, mw,
                     cell_cent, E, nu, mu, bulk, gamma, omega_fun, u_disp)

        K_bound, fb = peridym_apply_bc(K, bc_type, bc_vals, cell_cent,
                                       cell_vol, node_ids_dir, node_ids_frc,
                                       struct_grd)

        img_name = 'fracture_test_' + str(i).zfill(3) + '.png'
        if save_fig:
            data_dir = path.join(data_dir_top, img_name)
        else:
            data_dir = None
        u_disp = direct_solver(K_bound, fb, dim, reshape=True)
        cell_cent_orig, u_disp_orig, u_disp_ghost = recover_original_peridynamic_mesh(
            cell_cent, u_disp, bc_type, ghost_lyr_node_ids, struct_grd)
        disp_cent = get_displaced_soln(cell_cent_orig,
                                       u_disp_orig,
                                       horizon,
                                       dim,
                                       data_dir,
                                       plot_=pplot,
                                       save_fig=save_fig,
                                       zoom=10)

        u_disp = u_disp_ghost
        cell_cent += u_disp

        print("END : time step %i" % i)
        print("********************************************")
        print("********************************************")