tdo not store overlap, begin implementing tangential elasticity - Granular.jl - Julia package for granular dynamics simulation
 (HTM) git clone git://src.adamsgaard.dk/Granular.jl
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 5e16f290d31e8d0d24032fc60ec40a5dfbcf52f6
 (DIR) parent b3a11d3fab0cc139a56290b080d1b68917566ee8
 (HTM) Author: Anders Damsgaard <andersd@riseup.net>
       Date:   Tue,  9 May 2017 12:12:52 -0400
       
       do not store overlap, begin implementing tangential elasticity
       
       Diffstat:
         M src/contact_search.jl               |       1 -
         M src/datatypes.jl                    |       1 -
         M src/interaction.jl                  |      50 ++++++++++++++++++++++----------
         M src/simulation.jl                   |       3 ---
         M test/contact-search-and-geometry.jl |      20 --------------------
       
       5 files changed, 35 insertions(+), 40 deletions(-)
       ---
 (DIR) diff --git a/src/contact_search.jl b/src/contact_search.jl
       t@@ -136,7 +136,6 @@ function checkAndAddContact!(simulation::Simulation, i::Int, j::Int)
                # Check if grains overlap (overlap when negative)
                if overlap_ij < 0.0
                    push!(simulation.contact_pairs, [i, j])
       -            push!(simulation.overlaps, overlap_ij*position_ij/norm(position_ij))
                    push!(simulation.contact_parallel_displacement, zeros(2))
                end
            end
 (DIR) diff --git a/src/datatypes.jl b/src/datatypes.jl
       t@@ -172,7 +172,6 @@ type Simulation
        
            ice_floes::Array{IceFloeCylindrical, 1}
            contact_pairs::Array{Array{Int, 1}, 1}
       -    overlaps::Array{Array{Float64, 1}, 1}
            contact_parallel_displacement::Array{Array{Float64, 1}, 1}
        
            ocean::Ocean
 (DIR) diff --git a/src/interaction.jl b/src/interaction.jl
       t@@ -11,11 +11,10 @@ function interact!(simulation::Simulation;
            # IceFloe to grain collisions
            while !isempty(simulation.contact_pairs)
                contact_pair = pop!(simulation.contact_pairs)
       -        overlap = pop!(simulation.overlaps)
                contact_parallel_displacement = 
                    pop!(simulation.contact_parallel_displacement)
                interactIceFloes!(simulation, contact_pair[1], contact_pair[2],
       -                          overlap, contact_parallel_displacement,
       +                          contact_parallel_displacement,
                                  contact_normal_rheology=contact_normal_rheology,
                                  contact_tangential_rheology=
                                      contact_tangential_rheology)
       t@@ -30,23 +29,24 @@ function adds the compressive force of the interaction to the ice floe
        """
        function interactIceFloes!(simulation::Simulation,
                                   i::Int, j::Int,
       -                           overlap::vector,
                                   contact_parallel_displacement::vector;
                                   contact_normal_rheology::String = "Linear Elastic",
                                   contact_tangential_rheology::String = "None")
        
       -    force_n = 0.
       -    force_t = 0.
       +    force_n = 0.  # Contact-normal force
       +    force_t = 0.  # Contact-parallel (tangential) force
        
       +    # Inter-position vector
            p = simulation.ice_floes[i].lin_pos - simulation.ice_floes[j].lin_pos
            dist = norm(p)
        
            r_i = simulation.ice_floes[i].contact_radius
            r_j = simulation.ice_floes[j].contact_radius
        
       -    dn = dist - (r_i + r_j)
       +    # Floe distance
       +    delta_n = dist - (r_i + r_j)
        
       -    if dn < 0.  # Contact (this should always occur)
       +    if delta_n < 0.  # Contact (this should always occur)
        
                # Local axes
                n = p/dist
       t@@ -60,9 +60,15 @@ function interactIceFloes!(simulation::Simulation,
                    harmonicMean(r_i, r_j)*(simulation.ice_floes[i].ang_vel +
                                            simulation.ice_floes[j].ang_vel)
        
       +        # Correct old tangential displacement for contact rotation and add new
       +        delta_t = dot(t, contact_parallel_displacement -
       +                      (n*dot(n, contact_parallel_displacement))) +
       +            vel_t*simulation.time_step
       +
       +        # Effective radius
                R_ij = harmonicMean(simulation.ice_floes[i].contact_radius,
       -                            simulation.ice_floes[j].contact_radius) -
       -               norm(overlap)/2.
       +                            simulation.ice_floes[j].contact_radius) - 
       +            abs(delta_n)/2.
        
                # Contact mechanical parameters
                k_n_harmonic_mean = 
       t@@ -87,29 +93,41 @@ function interactIceFloes!(simulation::Simulation,
                # Determine contact forces
                if contact_normal_rheology == "None"
                    force_n = 0.
       +
                elseif contact_normal_rheology == "Linear Elastic"
       -            force_n = -k_n_harmonic_mean*dn
       +            force_n = -k_n_harmonic_mean*delta_n
       +
                elseif contact_normal_rheology == "Linear Viscous Elastic"
       -            force_n = -k_n_harmonic_mean*dn - gamma_n_harmonic_mean*vel_n
       +            force_n = -k_n_harmonic_mean*delta_n - gamma_n_harmonic_mean*vel_n
                    if force_n < 0.
                        force_n = 0.
                    end
       +
                else
                    error("unknown contact_normal_rheology '$contact_normal_rheology'")
                end
        
                if contact_tangential_rheology == "None"
                    # do nothing
       -        elseif contact_tangential_rheology == "Linear Elastic Frictional"
       -            error("not yet implemented")
       +
       +        elseif contact_tangential_rheology ==
       +            "Linear Elastic Viscous Frictional"
       +            force_t = -k_t_harmonic_mean*delta_t - gamma_t_harmonic_mean*vel_t
       +            if abs(force_t) > mu_d_minimum*abs(force_n)
       +                force_t = mu_d_minimum*abs(force_n)*force_t/abs(force_t)
       +                delta_t = (-force_t - gamma_t_harmonic_mean*vel_t)/
       +                    k_t_harmonic_mean
       +            end
       +
                elseif contact_tangential_rheology == "Linear Viscous Frictional"
                    force_t = abs(gamma_t_harmonic_mean * vel_t)
       -            if force_t > mu_d_minimum*norm(force_n)
       -                force_t = mu_d_minimum*norm(force_n)
       +            if force_t > mu_d_minimum*abs(force_n)
       +                force_t = mu_d_minimum*abs(force_n)
                    end
                    if vel_t > 0.
                        force_t = -force_t
                    end
       +
                else
                    error("unknown contact_tangential_rheology ", 
                          "'$contact_tangential_rheology'")
       t@@ -120,6 +138,8 @@ function interactIceFloes!(simulation::Simulation,
                      "floes $i and $j")
            end
        
       +    contact_parallel_displacement = delta_t*t
       +
            simulation.ice_floes[i].force += force_n*n + force_t*t;
            simulation.ice_floes[j].force -= force_n*n + force_t*t;
        
 (DIR) diff --git a/src/simulation.jl b/src/simulation.jl
       t@@ -11,7 +11,6 @@ export createSimulation
                              file_number::Int=0,
                              ice_floes=Array{IceFloeCylindrical, 1}[],
                              contact_pairs=Array{Int64, 1}[],
       -                      overlaps=Array{Array{Float64, 1}, 1}[],
                              contact_parallel_displacement=
                                  Array{Array{Float64, 1}, 1}[])
        
       t@@ -31,7 +30,6 @@ function createSimulation(;id::String="unnamed",
                                  file_time_since_output_file::Float64=0.,
                                  ice_floes=Array{IceFloeCylindrical, 1}[],
                                  contact_pairs=Array{Int64, 1}[],
       -                          overlaps=Array{Array{Float64, 1}, 1}[],
                                  contact_parallel_displacement=
                                      Array{Array{Float64, 1}, 1}[],
                                  ocean::Ocean=createEmptyOcean())
       t@@ -46,7 +44,6 @@ function createSimulation(;id::String="unnamed",
                              file_time_since_output_file,
                              ice_floes,
                              contact_pairs,
       -                      overlaps,
                              contact_parallel_displacement,
                              ocean)
        end
 (DIR) diff --git a/test/contact-search-and-geometry.jl b/test/contact-search-and-geometry.jl
       t@@ -20,10 +20,8 @@ info("Testing findContactsAllToAll(...)")
        sim_copy = deepcopy(sim)
        SeaIce.findContactsAllToAll!(sim)
        
       -@test 1 == length(sim.overlaps)
        @test 1 == length(sim.contact_pairs)
        @test_approx_eq [1, 2] sim.contact_pairs[1]
       -@test_approx_eq [2., 0.] sim.overlaps[1]
        
        
        info("Testing findContacts(...)")
       t@@ -31,19 +29,15 @@ sim = deepcopy(sim_copy)
        SeaIce.findContacts!(sim)
        
        sim.ice_floes[1].fixed = true
       -@test 1 == length(sim.overlaps)
        @test 1 == length(sim.contact_pairs)
        @test_approx_eq [1, 2] sim.contact_pairs[1]
       -@test_approx_eq [2., 0.] sim.overlaps[1]
        
        info("Testing findContacts(...)")
        sim = deepcopy(sim_copy)
        SeaIce.findContacts!(sim)
        
       -@test 1 == length(sim.overlaps)
        @test 1 == length(sim.contact_pairs)
        @test_approx_eq [1, 2] sim.contact_pairs[1]
       -@test_approx_eq [2., 0.] sim.overlaps[1]
        
        @test_throws ErrorException SeaIce.findContacts!(sim, method="")
        
       t@@ -51,20 +45,17 @@ sim = deepcopy(sim_copy)
        sim.ice_floes[1].fixed = true
        sim.ice_floes[2].fixed = true
        SeaIce.findContacts!(sim)
       -@test 0 == length(sim.overlaps)
        @test 0 == length(sim.contact_pairs)
        
        sim = deepcopy(sim_copy)
        SeaIce.disableIceFloe!(sim, 1)
        SeaIce.findContacts!(sim)
       -@test 0 == length(sim.overlaps)
        @test 0 == length(sim.contact_pairs)
        
        sim = deepcopy(sim_copy)
        SeaIce.disableIceFloe!(sim, 1)
        SeaIce.disableIceFloe!(sim, 2)
        SeaIce.findContacts!(sim)
       -@test 0 == length(sim.overlaps)
        @test 0 == length(sim.contact_pairs)
        
        info("Testing if interact(...) removes contacts correctly")
       t@@ -73,10 +64,8 @@ SeaIce.findContacts!(sim)
        SeaIce.interact!(sim)
        SeaIce.findContacts!(sim)
        
       -@test 1 == length(sim.overlaps)
        @test 1 == length(sim.contact_pairs)
        @test_approx_eq [1, 2] sim.contact_pairs[1]
       -@test_approx_eq [2., 0.] sim.overlaps[1]
        
        info("Testing findContactsOceanGrid(...)")
        sim = deepcopy(sim_copy)
       t@@ -84,10 +73,8 @@ sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.])
        SeaIce.sortIceFloesInOceanGrid!(sim)
        SeaIce.findContactsOceanGrid!(sim)
        
       -@test 1 == length(sim.overlaps)
        @test 1 == length(sim.contact_pairs)
        @test_approx_eq [1, 2] sim.contact_pairs[1]
       -@test_approx_eq [2., 0.] sim.overlaps[1]
        
        sim = deepcopy(sim_copy)
        sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.])
       t@@ -95,10 +82,8 @@ sim.ice_floes[1].fixed = true
        SeaIce.sortIceFloesInOceanGrid!(sim)
        SeaIce.findContactsOceanGrid!(sim)
        
       -@test 1 == length(sim.overlaps)
        @test 1 == length(sim.contact_pairs)
        @test_approx_eq [1, 2] sim.contact_pairs[1]
       -@test_approx_eq [2., 0.] sim.overlaps[1]
        
        sim = deepcopy(sim_copy)
        sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.])
       t@@ -107,7 +92,6 @@ sim.ice_floes[2].fixed = true
        SeaIce.sortIceFloesInOceanGrid!(sim)
        SeaIce.findContactsOceanGrid!(sim)
        
       -@test 0 == length(sim.overlaps)
        @test 0 == length(sim.contact_pairs)
        
        info("Testing findContacts(...)")
       t@@ -116,14 +100,10 @@ sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.])
        SeaIce.sortIceFloesInOceanGrid!(sim)
        SeaIce.findContacts!(sim)
        
       -@test 1 == length(sim.overlaps)
        @test 1 == length(sim.contact_pairs)
        @test_approx_eq [1, 2] sim.contact_pairs[1]
       -@test_approx_eq [2., 0.] sim.overlaps[1]
        
       -@test 1 == length(sim.overlaps)
        @test 1 == length(sim.contact_pairs)
        @test_approx_eq [1, 2] sim.contact_pairs[1]
       -@test_approx_eq [2., 0.] sim.overlaps[1]
        
        @test_throws ErrorException SeaIce.findContacts!(sim, method="")