tallow contacts to break and keep track of contact age - granular - granular dynamics simulation
 (HTM) git clone git://src.adamsgaard.dk/granular
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 0fe34fa5175dd35819839ff25ac866300fa82713
 (DIR) parent 35334244861f0274779e5f5df8936931e8649c49
 (HTM) Author: Anders Damsgaard <anders@adamsgaard.dk>
       Date:   Thu, 22 Apr 2021 09:52:03 +0200
       
       allow contacts to break and keep track of contact age
       
       Diffstat:
         M grains.c                            |      23 ++++++++++++++++++-----
         M grains.h                            |       2 +-
         M simulation.c                        |      10 +++-------
       
       3 files changed, 22 insertions(+), 13 deletions(-)
       ---
 (DIR) diff --git a/grains.c b/grains.c
       t@@ -125,22 +125,30 @@ grains_maximum_grain_edge(const struct grain *grains, size_t ng, int d)
        
        /* Hertz-Mindlin contact model for compressible spheres */
        void
       -grains_interact(struct grain *g_i, struct grain *g_j, int ic)
       +grains_interact(struct grain *g_i, struct grain *g_j, int ic, double dt)
        {
                int d;
                double f_n_ij[3], f_t_ij[3],
                           v_ij[3], v_n_ij[3], v_t_ij[3], v_n_dot_n_ij,
                       delta_ij,
       -                   n_ij[3], u_t_ij[3],
       +                   n_ij[3],
                           d_i, d_j,
                           r_ij[3], r_ij_norm,
                       m_i, m_j, m_ij,
                           E_ij, nu_ij, mu_ij,
                           gamma_n_ij, gamma_t_ij,
                       k_n_ij, k_t_ij, A_ij,
       -                   angvel_ij[3], *angvel_cross_r_ij, *f_t_cross_r_ij;
       +                   angvel_ij[3], u_t_dot_v_ij,
       +                   *angvel_cross_r_ij, *f_t_cross_r_ij;
        
                delta_ij = g_i->contacts[ic].overlap;
       +
       +        if (delta_ij < 0.0) {  /* TODO: implement tensile strength */
       +                g_i->contacts[ic].active = 0;
       +                g_i->ncontacts--;
       +                return;
       +        }
       +
                d_i = g_i->diameter;
                d_j = g_j->diameter;
                m_i = grain_mass(g_i);
       t@@ -163,7 +171,6 @@ grains_interact(struct grain *g_i, struct grain *g_j, int ic)
                        v_t_ij[d] = v_ij[d] - v_n_ij[d] - 0.5 * angvel_cross_r_ij[d];
                }
        
       -
                E_ij = fmin(g_i->youngs_modulus, g_j->youngs_modulus);
                nu_ij = fmin(g_i->poissons_ratio, g_j->poissons_ratio);
                mu_ij = fmin(g_i->friction_coeff, g_j->friction_coeff);
       t@@ -178,7 +185,7 @@ grains_interact(struct grain *g_i, struct grain *g_j, int ic)
                for (d = 0; d < 3; d++) {
                        f_n_ij[d] = A_ij * (k_n_ij * delta_ij * n_ij[d] 
                                                                - m_ij * gamma_n_ij * v_n_ij[d]);
       -                f_t_ij[d] = A_ij * (-k_t_ij * u_t_ij[d]
       +                f_t_ij[d] = A_ij * (-k_t_ij * g_i->contacts[ic].tandisp[d]
                                            - m_ij * gamma_t_ij * v_t_ij[d]);
                }
        
       t@@ -194,6 +201,12 @@ grains_interact(struct grain *g_i, struct grain *g_j, int ic)
                        g_j->torque[d] -= -0.5 * f_t_cross_r_ij[d];
                }
        
       +        g_i->contacts[ic].age += dt;
       +        u_t_dot_v_ij = dot(g_i->contacts[ic].tandisp, v_ij, 3);
       +        for (d = 0; d < 3; d++)
       +                g_i->contacts[ic].tandisp[d] += v_t_ij[d] * dt
       +                                              - u_t_dot_v_ij / (r_ij_norm * r_ij_norm);
       +
                free(angvel_cross_r_ij);
                free(f_t_cross_r_ij);
        }
 (DIR) diff --git a/grains.h b/grains.h
       t@@ -8,6 +8,6 @@ void grains_print_vtk(FILE *stream, const struct grain *grains, size_t ng);
        
        double sim_minimum_grain_edge(const struct grain *grains, size_t ng, int d);
        double sim_maximum_grain_edge(const struct grain *grains, size_t ng, int d);
       -void grains_interact(struct grain *g_i, struct grain *g_j, int nc);
       +void grains_interact(struct grain *g_i, struct grain *g_j, int nc, double dt);
        
        #endif
 (DIR) diff --git a/simulation.c b/simulation.c
       t@@ -107,24 +107,20 @@ static void
        sim_check_add_contact(struct simulation *sim, size_t i, size_t j)
        {
        
       -        double overlap, centerdist[3], centerdistinv[3];
       +        double overlap, centerdist[3];
                int d;
        
                if (i >= j)
                        return;
        
       -        for (d = 0; d < 3; d++) {
       +        for (d = 0; d < 3; d++)
                        centerdist[d] = sim->grains[i].pos[d] - sim->grains[j].pos[d];
       -                centerdistinv[d] = sim->grains[j].pos[d] - sim->grains[i].pos[d];
       -        }
        
                overlap = 0.5*(sim->grains[i].diameter + sim->grains[j].diameter)
                        - euclidean_norm(centerdist, 3);
        
                if (sim->grains[i].enabled)
                        grain_register_contact(&sim->grains[i], j, i, centerdist, overlap);
       -        if (sim->grains[j].enabled)
       -                grain_register_contact(&sim->grains[j], i, j, centerdistinv, overlap);
        }
        
        /* TODO: add grid sorting */
       t@@ -152,7 +148,7 @@ sim_resolve_interactions(struct simulation *sim)
                                    i < sim->grains[i].contacts[ic].j)
                                        grains_interact(&sim->grains[i],
                                                        &sim->grains[sim->grains[i].contacts[ic].j],
       -                                                ic);
       +                                                ic, sim->dt);
        }
        
        void