ttest additional collisions, rotational tests will fail - 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 784fc626abb1dde66a6aed241677ad8d5d8b53ac
 (DIR) parent bb21ec79edd4b21786d862d659daca6b2cbacc34
 (HTM) Author: Anders Damsgaard <andersd@riseup.net>
       Date:   Mon,  8 May 2017 16:57:16 -0400
       
       ttest additional collisions, rotational tests will fail
       
       Diffstat:
         M src/contact_search.jl               |      31 +++++++++++++++++++++++--------
         M src/interaction.jl                  |     145 +++++++++++++++++++++++--------
         M test/collision-2floes-oblique.jl    |     132 +++++++++++++++++++++++++++++++
         M test/contact-search-and-geometry.jl |      18 +++++++++---------
       
       4 files changed, 275 insertions(+), 51 deletions(-)
       ---
 (DIR) diff --git a/src/contact_search.jl b/src/contact_search.jl
       t@@ -30,9 +30,20 @@ function findContacts!(simulation::Simulation;
        end
        
        export interIceFloePositionVector
       +"""
       +    interIceFloePositionVector(simulation, i, j)
       +
       +Returns a `vector` pointing from ice floe `i` to ice floe `j` in the 
       +`simulation`.
       +
       +# Arguments
       +* `simulation::Simulation`: the simulation object containing the ice floes.
       +* `i::Int`: index of the first ice floe.
       +* `j::Int`: index of the second ice floe.
       +"""
        function interIceFloePositionVector(simulation::Simulation,
                                            i::Integer, j::Integer)
       -    return simulation.ice_floes[j].lin_pos - simulation.ice_floes[i].lin_pos
       +    return simulation.ice_floes[i].lin_pos - simulation.ice_floes[j].lin_pos
        end
        
        """
       t@@ -95,20 +106,24 @@ end
        
        export addContact!
        """
       -checkAndAddContact!(simulation, i, j)
       +    checkAndAddContact!(simulation, i, j)
        
       -Check for contact between two ice floes and register the interaction.
       +Check for contact between two ice floes and register the interaction in the 
       +`simulation` object.  The indexes of the two ice floes is stored in 
       +`simulation.contact_pairs` as `[i, j]`.  The overlap vector is parallel to a 
       +straight line connecting the ice floe centers, points away from ice floe `i` and 
       +towards `j`, and is stored in `simulation.overlaps`.  A zero-length vector is 
       +written to `simulation.contact_parallel_displacement`.
        
        # Arguments
       -* `simulation::Simulation`: the simulation object containing the ice floes
       -* `i::Int`: index of the first ice floe
       -* `j::Int`: index of the second ice floe
       +* `simulation::Simulation`: the simulation object containing the ice floes.
       +* `i::Int`: index of the first ice floe.
       +* `j::Int`: index of the second ice floe.
        """
        function checkAndAddContact!(simulation::Simulation, i::Int, j::Int)
            if i < j
        
       -        if (simulation.ice_floes[i].fixed &&
       -            simulation.ice_floes[j].fixed) ||
       +        if (simulation.ice_floes[i].fixed && simulation.ice_floes[j].fixed) ||
                    !simulation.ice_floes[i].enabled ||
                    !simulation.ice_floes[j].enabled
                    return
 (DIR) diff --git a/src/interaction.jl b/src/interaction.jl
       t@@ -11,11 +11,11 @@ function interact!(simulation::Simulation;
            # IceFloe to grain collisions
            while !isempty(simulation.contact_pairs)
                contact_pair = pop!(simulation.contact_pairs)
       -        overlap_vector = pop!(simulation.overlaps)
       +        overlap = pop!(simulation.overlaps)
                contact_parallel_displacement = 
                    pop!(simulation.contact_parallel_displacement)
                interactIceFloes!(simulation, contact_pair[1], contact_pair[2],
       -                          overlap_vector, contact_parallel_displacement,
       +                          overlap, contact_parallel_displacement,
                                  contact_normal_rheology=contact_normal_rheology,
                                  contact_tangential_rheology=
                                      contact_tangential_rheology)
       t@@ -30,8 +30,8 @@ function adds the compressive force of the interaction to the ice floe
        """
        function interactIceFloes!(simulation::Simulation,
                                   i::Int, j::Int,
       -                           overlap_vector::Array{Float64, 1},
       -                           contact_parallel_displacement::Array{Float64, 1};
       +                           overlap::vector,
       +                           contact_parallel_displacement::vector;
                                   contact_normal_rheology::String = "Linear Elastic",
                                   contact_tangential_rheology::String = "None")
        
       t@@ -41,7 +41,7 @@ function interactIceFloes!(simulation::Simulation,
            if contact_normal_rheology == "None"
                # do nothing
            elseif contact_normal_rheology == "Linear Elastic"
       -        force_n = interactNormalLinearElastic(simulation, i, j, overlap_vector)
       +        force_n = interactNormalLinearElastic(simulation, i, j, overlap)
            else
                error("Unknown contact_normal_rheology '$contact_normal_rheology'")
            end
       t@@ -50,7 +50,7 @@ function interactIceFloes!(simulation::Simulation,
                # do nothing
            elseif contact_tangential_rheology == "Linear Viscous Frictional"
                force_t = interactTangentialLinearViscousFrictional(simulation, i, j,
       -                                                            overlap_vector,
       +                                                            overlap,
                                                                    force_n)
            else
                error("Unknown contact_tangential_rheology ", 
       t@@ -61,7 +61,7 @@ function interactIceFloes!(simulation::Simulation,
            simulation.ice_floes[j].force -= force_n + force_t;
        
            if norm(force_t) > 0.
       -        torque = -findTorque(simulation, overlap_vector, force_t, i, j)
       +        torque = -findTorque(simulation, overlap, force_t, i, j)
                simulation.ice_floes[i].torque += torque
                simulation.ice_floes[j].torque += torque
            end
       t@@ -79,46 +79,108 @@ direction.
        """
        function interactNormalLinearElastic(simulation::Simulation,
                                             i::Int, j::Int,
       -                                     overlap_vector::vector)
       +                                     overlap::vector)
        
            k_n_harmonic_mean = 
                harmonicMean(simulation.ice_floes[i].contact_stiffness_normal,
                             simulation.ice_floes[j].contact_stiffness_normal)
        
       -    return k_n_harmonic_mean * overlap_vector
       +    return -k_n_harmonic_mean*overlap
        end
        
        export interactTangentialLinearElastic
        """
       -Resolves linear-elastic interaction between two ice floes in the 
       -contact-parallel (tangential) direction.
       +    interactTangentialLinearViscousFrictional(simulation, i, j,
       +                                              overlap, force_n)
       +
       +Resolves linear-viscous interaction between two ice floes in the contact- 
       +parallel (tangential) direction, with a frictional limit dependent on the 
       +Coulomb criterion.
       +
       +# Arguments
       +* `simulation::Simulation`: the simulation object containing the ice floes.
       +* `i::Int`: index of the first ice floe.
       +* `j::Int`: index of the second ice floe.
       +* `overlap::vector`: two-dimensional vector pointing from i to j.
       +* `force_n::vector`: normal force from the interaction.
        """
        function interactTangentialLinearViscousFrictional(simulation::Simulation,
                                                           i::Int, j::Integer,
       -                                                   overlap_vector::vector,
       +                                                   overlap::vector,
                                                           force_n::vector)
        
       +    """
            contact_parallel_velocity = findContactParallelVelocity(simulation, i, j, 
       -                                                            overlap_vector)
       +                                                            overlap)
        
       -    if norm(contact_parallel_velocity) ≈ 0.
       +
       +
       +    if contact_parallel_velocity ≈ 0.
                return [0., 0.]
            end
       -
            gamma_t_harmonic_mean = harmonicMean(
                             simulation.ice_floes[i].contact_viscosity_tangential,
                             simulation.ice_floes[j].contact_viscosity_tangential)
       +    mu_d_minimum = min(simulation.ice_floes[i].contact_dynamic_friction,
       +                       simulation.ice_floes[j].contact_dynamic_friction)
        
       -    if norm(gamma_t_harmonic_mean) ≈ 0.
       +    if gamma_t_harmonic_mean ≈ 0. || mu_d_minimum ≈ 0.
                return [0., 0.]
            end
        
       -    mu_d_minimum = min(simulation.ice_floes[i].contact_dynamic_friction,
       -                       simulation.ice_floes[j].contact_dynamic_friction)
       +    force_t = abs(gamma_t_harmonic_mean*contact_parallel_velocity)
       +    if force_t > mu_d_minimum*norm(force_n)
       +        force_t = mu_d_minimum*norm(force_n)
       +    end
       +    if contact_parallel_velocity > 0.
       +        force_t = -force_t
       +    end
       +
       +    return force_t*contactParallelVector(contactNormalVector(overlap))
       +    """
       +
       +    p = simulation.ice_floes[i].lin_pos - simulation.ice_floes[j].lin_pos
       +
       +    r_i = simulation.ice_floes[i].contact_radius
       +    r_j = simulation.ice_floes[j].contact_radius
       +
       +    dist = norm(p)
       +    dn = dist - (r_i + r_j)
       +
       +    if dn < 0.
       +        n = p/dist
       +        t = [-n[2], n[1]]
       +
       +        vel_lin = simulation.ice_floes[i].lin_vel -
       +            simulation.ice_floes[j].lin_vel
       +
       +        vel_n = dot(vel_lin, n)
       +        vel_t = dot(vel_lin, t) -
       +            harmonicMean(r_i, r_j)*(simulation.ice_floes[i].ang_vel +
       +                                    simulation.ice_floes[j].ang_vel)
       +
       +        #force_n = -kn * dn - nu * vn;
       +
       +        gamma_t_harmonic_mean = harmonicMean(
       +                     simulation.ice_floes[i].contact_viscosity_tangential,
       +                     simulation.ice_floes[j].contact_viscosity_tangential)
       +
       +        force_t = abs(gamma_t_harmonic_mean * vel_t)
       +
       +        mu_d_minimum = min(simulation.ice_floes[i].contact_dynamic_friction,
       +                           simulation.ice_floes[j].contact_dynamic_friction)
       +
       +        if force_t > mu_d_minimum*norm(force_n)
       +            force_t = mu_d_minimum*norm(force_n)
       +        end
       +        if vel_t > 0.
       +            force_t = -force_t
       +        end
       +
       +        return force_t*t
       +
       +    end
        
       -    return -min(norm(gamma_t_harmonic_mean*contact_parallel_velocity), 
       -                mu_d_minimum*norm(force_n))*
       -        contact_parallel_velocity/norm(contact_parallel_velocity)
        end
        
        function harmonicMean(a::Any, b::Any)
       t@@ -129,24 +191,39 @@ function harmonicMean(a::Any, b::Any)
            return hm
        end
        
       -function findTorque(simulation::Simulation, overlap_vector::vector, 
       -                    force_t::vector, i::Int, j::Int)
       -    n = overlap_vector/norm(overlap_vector)
       -    return -findEffectiveRadius(simulation, i, j, overlap_vector)*
       -        (n[1]*force_t[2] - n[2]*force_t[1])
       +function findTorque(simulation::Simulation, overlap::vector, force_t::vector, 
       +                    i::Int, j::Int)
       +    return -findEffectiveRadius(simulation, i, j, overlap)*norm(force_t)
        end
        
        function findEffectiveRadius(simulation::Simulation, i::Int, j::Int,
       -                             overlap_vector::vector)
       +                             overlap::vector)
            return harmonicMean(simulation.ice_floes[i].contact_radius,
       -                        simulation.ice_floes[j].contact_radius)
       -                        - norm(overlap_vector)/2.
       +                        simulation.ice_floes[j].contact_radius) -
       +                        norm(overlap)/2.
       +end
       +
       +function findContactNormalVelocity(simulation::Simulation, i::Int, j::Int,
       +                                   overlap::vector)
       +    n = contactNormalVector(overlap)
       +    v_ij = simulation.ice_floes[i].lin_vel - simulation.ice_floes[j].lin_vel
       +    return v_ij[1]*n[1] + v_ij[2]*n[2]
        end
        
        function findContactParallelVelocity(simulation::Simulation, i::Int, j::Int,
       -                                     overlap_vector::vector)
       -    return simulation.ice_floes[i].lin_vel -
       -        simulation.ice_floes[j].lin_vel +
       -        findEffectiveRadius(simulation, i, j, overlap_vector)*
       -        (simulation.ice_floes[i].ang_vel + simulation.ice_floes[j].ang_vel)
       +                                     overlap::vector)
       +    v_ij = simulation.ice_floes[i].lin_vel - simulation.ice_floes[j].lin_vel
       +    n = contactNormalVector(overlap)
       +    t = contactParallelVector(n)
       +    return (v_ij[1]*t[1] + v_ij[2]*t[2] -
       +        findEffectiveRadius(simulation, i, j, overlap)*
       +        (simulation.ice_floes[i].ang_vel + simulation.ice_floes[j].ang_vel))
       +end
       +
       +function contactNormalVector(overlap::vector)
       +    return overlap/norm(overlap)
       +end
       +
       +function contactParallelVector(n::vector)
       +    return [-n[2], n[1]]
        end
 (DIR) diff --git a/test/collision-2floes-oblique.jl b/test/collision-2floes-oblique.jl
       t@@ -318,7 +318,73 @@ E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
        info("Testing kinetic energy conservation with Three-term Taylor scheme")
        sim = deepcopy(sim_init)
        SeaIce.setTimeStep!(sim, epsilon=0.07)
       +tol = 0.04
       +info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)")
       +SeaIce.run!(sim, temporal_integration_method="Three-term Taylor",
       +            contact_tangential_rheology="Linear Viscous Frictional", 
       +            verbose=verbose)
       +
       +@test sim.ice_floes[1].ang_pos > 0.
       +@test sim.ice_floes[1].ang_vel > 0.
       +@test sim.ice_floes[2].ang_pos > 0.
       +@test sim.ice_floes[2].ang_vel > 0.
       +E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
       +E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
       +@test_approx_eq_eps E_kin_lin_init+E_kin_rot_init E_kin_lin_final+E_kin_rot_final E_kin_lin_init*tol 
       +
       +
       +info("# Ice floes free to move, mirrored")
       +
       +sim = SeaIce.createSimulation(id="test")
       +SeaIce.addIceFloeCylindrical(sim, [0., 0.], 10., 1., verbose=verbose)
       +SeaIce.addIceFloeCylindrical(sim, [19.0, 10.], 10., 1., verbose=verbose)
       +sim.ice_floes[2].lin_vel[1] = -0.1
       +sim.ice_floes[1].contact_viscosity_tangential = 1e4
       +sim.ice_floes[2].contact_viscosity_tangential = 1e4
       +
       +E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
       +E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
       +
       +# With decreasing timestep (epsilon towards 0), the explicit integration scheme 
       +# should become more correct
       +
       +SeaIce.setTotalTime!(sim, 30.0)
       +sim_init = deepcopy(sim)
       +
       +info("Testing kinetic energy conservation with Two-term Taylor scheme")
       +SeaIce.setTimeStep!(sim, epsilon=0.07)
       +tol = 0.2
       +info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)")
       +SeaIce.run!(sim, temporal_integration_method="Two-term Taylor",
       +            contact_tangential_rheology="Linear Viscous Frictional", 
       +            verbose=verbose)
       +
       +@test sim.ice_floes[1].ang_pos > 0.
       +@test sim.ice_floes[1].ang_vel > 0.
       +@test sim.ice_floes[2].ang_pos > 0.
       +@test sim.ice_floes[2].ang_vel > 0.
       +E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
       +E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
       +@test_approx_eq_eps E_kin_lin_init+E_kin_rot_init E_kin_lin_final+E_kin_rot_final E_kin_lin_init*tol 
       +
       +info("Testing kinetic energy conservation with Two-term Taylor scheme")
       +sim = deepcopy(sim_init)
       +SeaIce.setTimeStep!(sim, epsilon=0.007)
        tol = 0.05
       +info("Relative tolerance: $(tol*100.)%")
       +SeaIce.run!(sim, temporal_integration_method="Two-term Taylor",
       +            contact_tangential_rheology="Linear Viscous Frictional", 
       +            verbose=verbose)
       +
       +E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
       +E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
       +@test_approx_eq_eps E_kin_lin_init+E_kin_rot_init E_kin_lin_final+E_kin_rot_final E_kin_lin_init*tol 
       +
       +
       +info("Testing kinetic energy conservation with Three-term Taylor scheme")
       +sim = deepcopy(sim_init)
       +SeaIce.setTimeStep!(sim, epsilon=0.07)
       +tol = 0.04
        info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)")
        SeaIce.run!(sim, temporal_integration_method="Three-term Taylor",
                    contact_tangential_rheology="Linear Viscous Frictional", 
       t@@ -331,3 +397,69 @@ SeaIce.run!(sim, temporal_integration_method="Three-term Taylor",
        E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
        E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
        @test_approx_eq_eps E_kin_lin_init+E_kin_rot_init E_kin_lin_final+E_kin_rot_final E_kin_lin_init*tol 
       +
       +
       +info("# Ice floes free to move, mirrored #2")
       +
       +sim = SeaIce.createSimulation(id="test")
       +SeaIce.addIceFloeCylindrical(sim, [0., 0.], 10., 1., verbose=verbose)
       +SeaIce.addIceFloeCylindrical(sim, [19.0, -10.], 10., 1., verbose=verbose)
       +sim.ice_floes[2].lin_vel[1] = -0.1
       +sim.ice_floes[1].contact_viscosity_tangential = 1e4
       +sim.ice_floes[2].contact_viscosity_tangential = 1e4
       +
       +E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
       +E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
       +
       +# With decreasing timestep (epsilon towards 0), the explicit integration scheme 
       +# should become more correct
       +
       +SeaIce.setTotalTime!(sim, 30.0)
       +sim_init = deepcopy(sim)
       +
       +info("Testing kinetic energy conservation with Two-term Taylor scheme")
       +SeaIce.setTimeStep!(sim, epsilon=0.07)
       +tol = 0.2
       +info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)")
       +SeaIce.run!(sim, temporal_integration_method="Two-term Taylor",
       +            contact_tangential_rheology="Linear Viscous Frictional", 
       +            verbose=verbose)
       +
       +@test sim.ice_floes[1].ang_pos < 0.
       +@test sim.ice_floes[1].ang_vel < 0.
       +@test sim.ice_floes[2].ang_pos < 0.
       +@test sim.ice_floes[2].ang_vel < 0.
       +E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
       +E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
       +@test_approx_eq_eps E_kin_lin_init+E_kin_rot_init E_kin_lin_final+E_kin_rot_final E_kin_lin_init*tol 
       +
       +info("Testing kinetic energy conservation with Two-term Taylor scheme")
       +sim = deepcopy(sim_init)
       +SeaIce.setTimeStep!(sim, epsilon=0.007)
       +tol = 0.05
       +info("Relative tolerance: $(tol*100.)%")
       +SeaIce.run!(sim, temporal_integration_method="Two-term Taylor",
       +            contact_tangential_rheology="Linear Viscous Frictional", 
       +            verbose=verbose)
       +
       +E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
       +E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
       +@test_approx_eq_eps E_kin_lin_init+E_kin_rot_init E_kin_lin_final+E_kin_rot_final E_kin_lin_init*tol 
       +
       +
       +info("Testing kinetic energy conservation with Three-term Taylor scheme")
       +sim = deepcopy(sim_init)
       +SeaIce.setTimeStep!(sim, epsilon=0.07)
       +tol = 0.04
       +info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)")
       +SeaIce.run!(sim, temporal_integration_method="Three-term Taylor",
       +            contact_tangential_rheology="Linear Viscous Frictional", 
       +            verbose=verbose)
       +
       +@test sim.ice_floes[1].ang_pos < 0.
       +@test sim.ice_floes[1].ang_vel < 0.
       +@test sim.ice_floes[2].ang_pos < 0.
       +@test sim.ice_floes[2].ang_vel < 0.
       +E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim)
       +E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim)
       +@test_approx_eq_eps E_kin_lin_init+E_kin_rot_init E_kin_lin_final+E_kin_rot_final E_kin_lin_init*tol 
 (DIR) diff --git a/test/contact-search-and-geometry.jl b/test/contact-search-and-geometry.jl
       t@@ -12,7 +12,7 @@ SeaIce.addIceFloeCylindrical(sim, [18., 0.], 10., 1., verbose=false)
        position_ij = SeaIce.interIceFloePositionVector(sim, 1, 2)
        overlap_ij = SeaIce.findOverlap(sim, 1, 2, position_ij)
        
       -@test_approx_eq [18., 0.] position_ij
       +@test_approx_eq [-18., 0.] position_ij
        @test_approx_eq -2. overlap_ij
        
        
       t@@ -23,7 +23,7 @@ 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]
       +@test_approx_eq [2., 0.] sim.overlaps[1]
        
        
        info("Testing findContacts(...)")
       t@@ -34,7 +34,7 @@ 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]
       +@test_approx_eq [2., 0.] sim.overlaps[1]
        
        info("Testing findContacts(...)")
        sim = deepcopy(sim_copy)
       t@@ -43,7 +43,7 @@ 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_approx_eq [2., 0.] sim.overlaps[1]
        
        @test_throws ErrorException SeaIce.findContacts!(sim, method="")
        
       t@@ -76,7 +76,7 @@ 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_approx_eq [2., 0.] sim.overlaps[1]
        
        info("Testing findContactsOceanGrid(...)")
        sim = deepcopy(sim_copy)
       t@@ -87,7 +87,7 @@ 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]
       +@test_approx_eq [2., 0.] sim.overlaps[1]
        
        sim = deepcopy(sim_copy)
        sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.])
       t@@ -98,7 +98,7 @@ 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]
       +@test_approx_eq [2., 0.] sim.overlaps[1]
        
        sim = deepcopy(sim_copy)
        sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.])
       t@@ -119,11 +119,11 @@ 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_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_approx_eq [2., 0.] sim.overlaps[1]
        
        @test_throws ErrorException SeaIce.findContacts!(sim, method="")