Granular.jl

Julia package for granular dynamics simulation
git clone git://src.adamsgaard.dk/Granular.jl
Log | Files | Refs | README | LICENSE

commit 23fc4a029c9f5c4a8b4781eb1404f4049fda3add
parent 0440db5e1befd66a7f4c9fb98061d8f4604d56f1
Author: Anders Damsgaard <andersd@riseup.net>
Date:   Mon,  8 May 2017 21:18:02 -0400

concatenate interaction function, fix rotation issues

Diffstat:
Msrc/interaction.jl | 216++++++++++++++++++++++++-------------------------------------------------------
Mtest/collision-2floes-oblique.jl | 54+++++++++++++++++++++++++++---------------------------
2 files changed, 91 insertions(+), 179 deletions(-)

diff --git a/src/interaction.jl b/src/interaction.jl @@ -35,152 +35,101 @@ function interactIceFloes!(simulation::Simulation, contact_normal_rheology::String = "Linear Elastic", contact_tangential_rheology::String = "None") - force_n = zeros(2) - force_t = zeros(2) - - if contact_normal_rheology == "None" - # do nothing - elseif contact_normal_rheology == "Linear Elastic" - force_n = interactNormalLinearElastic(simulation, i, j, overlap) - else - error("Unknown contact_normal_rheology '$contact_normal_rheology'") - end - - if contact_tangential_rheology == "None" - # do nothing - elseif contact_tangential_rheology == "Linear Viscous Frictional" - force_t = interactTangentialLinearViscousFrictional(simulation, i, j, - overlap, - force_n) - else - error("Unknown contact_tangential_rheology ", - "'$contact_tangential_rheology'") - end - - simulation.ice_floes[i].force += force_n + force_t; - simulation.ice_floes[j].force -= force_n + force_t; - - if norm(force_t) > 0. - torque = -findTorque(simulation, overlap, force_t, i, j) - simulation.ice_floes[i].torque += torque - simulation.ice_floes[j].torque += torque - end - - simulation.ice_floes[i].pressure += - norm(force_n)/simulation.ice_floes[i].side_surface_area; - simulation.ice_floes[j].pressure += - norm(force_n)/simulation.ice_floes[j].side_surface_area; -end - -export interactNormalLinearElastic -""" -Resolves linear-elastic interaction between two ice floes in the contact-normal -direction. -""" -function interactNormalLinearElastic(simulation::Simulation, - i::Int, j::Int, - 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 -end - -export interactTangentialLinearElastic -""" - 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, - force_n::vector) - - """ - contact_parallel_velocity = findContactParallelVelocity(simulation, i, j, - overlap) - - - - 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 gamma_t_harmonic_mean ≈ 0. || mu_d_minimum ≈ 0. - return [0., 0.] - end - - 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)) - """ + force_n = 0. + force_t = 0. 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 - dist = norm(p) dn = dist - (r_i + r_j) - if dn < 0. + if dn < 0. # Contact (this should always occur) + + # Local axes n = p/dist t = [-n[2], n[1]] + # Contact kinematics 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; + R_ij = harmonicMean(simulation.ice_floes[i].contact_radius, + simulation.ice_floes[j].contact_radius) - + norm(overlap)/2. + + # Contact mechanical parameters + k_n_harmonic_mean = + harmonicMean(simulation.ice_floes[i].contact_stiffness_normal, + simulation.ice_floes[j].contact_stiffness_normal) + + k_t_harmonic_mean = + harmonicMean(simulation.ice_floes[i].contact_stiffness_tangential, + simulation.ice_floes[j].contact_stiffness_tangential) + + gamma_n_harmonic_mean = harmonicMean( + simulation.ice_floes[i].contact_viscosity_normal, + simulation.ice_floes[j].contact_viscosity_normal) 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 + # Determine contact forces + if contact_normal_rheology == "None" + force_n = 0. + elseif contact_normal_rheology == "Linear Elastic" + force_n = -k_n_harmonic_mean*dn + elseif contact_normal_rheology == "Linear Viscous Elastic" + force_n = -k_n_harmonic_mean*dn - gamma_n_harmonic_mean*vel_n + if force_n < 0. + force_n = 0. + end + else + error("unknown contact_normal_rheology '$contact_normal_rheology'") end - return force_t*t + if contact_tangential_rheology == "None" + # do nothing + elseif contact_tangential_rheology == "Linear Elastic Frictional" + error("not yet implemented") + 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) + end + if vel_t > 0. + force_t = -force_t + end + else + error("unknown contact_tangential_rheology ", + "'$contact_tangential_rheology'") + end + else + error("function called to process non-existent contact between ice " * + "floes $i and $j") end + simulation.ice_floes[i].force += force_n*n + force_t*t; + simulation.ice_floes[j].force -= force_n*n + force_t*t; + + simulation.ice_floes[i].torque += -force_t*R_ij + simulation.ice_floes[j].torque += -force_t*R_ij + + simulation.ice_floes[i].pressure += + force_n/simulation.ice_floes[i].side_surface_area; + simulation.ice_floes[j].pressure += + force_n/simulation.ice_floes[j].side_surface_area; end function harmonicMean(a::Any, b::Any) @@ -190,40 +139,3 @@ function harmonicMean(a::Any, b::Any) end return hm end - -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) - return harmonicMean(simulation.ice_floes[i].contact_radius, - 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) - 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 diff --git a/test/collision-2floes-oblique.jl b/test/collision-2floes-oblique.jl @@ -27,7 +27,7 @@ sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") SeaIce.setTimeStep!(sim, epsilon=0.07) -tol = 0.2 +tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", contact_tangential_rheology="None", verbose=verbose) @@ -41,7 +41,7 @@ E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) SeaIce.setTimeStep!(sim, epsilon=0.007) -tol = 0.02 +tol = 0.01 info("Relative tolerance: $(tol*100.)%") SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", contact_tangential_rheology="None", verbose=verbose) @@ -83,7 +83,7 @@ sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") SeaIce.setTimeStep!(sim, epsilon=0.07) -tol = 0.2 +tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", contact_tangential_rheology="None", verbose=verbose) @@ -97,7 +97,7 @@ E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) SeaIce.setTimeStep!(sim, epsilon=0.007) -tol = 0.02 +tol = 0.01 info("Relative tolerance: $(tol*100.)%") SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", contact_tangential_rheology="None", verbose=verbose) @@ -140,7 +140,7 @@ sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") SeaIce.setTimeStep!(sim, epsilon=0.07) -tol = 0.2 +tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @@ -159,7 +159,7 @@ 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.02 +tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @@ -198,7 +198,7 @@ sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") SeaIce.setTimeStep!(sim, epsilon=0.07) -tol = 0.2 +tol = 0.1 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", @@ -216,7 +216,7 @@ info("mu_d = 0.") sim = deepcopy(sim_init) sim.ice_floes[1].contact_dynamic_friction = 0. SeaIce.setTimeStep!(sim, epsilon=0.07) -tol = 0.02 +tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @@ -235,7 +235,7 @@ E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) SeaIce.setTimeStep!(sim, epsilon=0.007) -tol = 0.06 +tol = 0.02 info("Relative tolerance: $(tol*100.)%") SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", contact_tangential_rheology="Linear Viscous Frictional", @@ -253,7 +253,7 @@ 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.07 +tol = 0.03 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", @@ -287,7 +287,7 @@ sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") SeaIce.setTimeStep!(sim, epsilon=0.07) -tol = 0.2 +tol = 0.1 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", @@ -304,7 +304,7 @@ E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) SeaIce.setTimeStep!(sim, epsilon=0.007) -tol = 0.05 +tol = 0.02 info("Relative tolerance: $(tol*100.)%") SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", contact_tangential_rheology="Linear Viscous Frictional", @@ -318,16 +318,16 @@ 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 +tol = 0.02 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. +@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 @@ -353,7 +353,7 @@ sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") SeaIce.setTimeStep!(sim, epsilon=0.07) -tol = 0.2 +tol = 0.1 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", @@ -370,7 +370,7 @@ E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) SeaIce.setTimeStep!(sim, epsilon=0.007) -tol = 0.05 +tol = 0.02 info("Relative tolerance: $(tol*100.)%") SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", contact_tangential_rheology="Linear Viscous Frictional", @@ -384,16 +384,16 @@ 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 +tol = 0.02 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. +@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 @@ -419,7 +419,7 @@ sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") SeaIce.setTimeStep!(sim, epsilon=0.07) -tol = 0.2 +tol = 0.1 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", @@ -436,7 +436,7 @@ E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) SeaIce.setTimeStep!(sim, epsilon=0.007) -tol = 0.05 +tol = 0.02 info("Relative tolerance: $(tol*100.)%") SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", contact_tangential_rheology="Linear Viscous Frictional", @@ -450,7 +450,7 @@ 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 +tol = 0.02 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",