Granular.jl

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

commit 7515db2c7960dea61383549159b3b94308a9fc75
parent dadd1cadc476c6f083ecf13f38110e453b465257
Author: Anders Damsgaard <andersd@riseup.net>
Date:   Wed, 10 May 2017 15:33:57 -0400

fix interaction scheme

Diffstat:
Msrc/contact_search.jl | 25+++++++++++++------------
Msrc/icefloe.jl | 45+++++++++++++++++++++++++++++++++++++++++++++
Msrc/interaction.jl | 18++++++++----------
Mtest/collision-5floes-normal.jl | 47++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 112 insertions(+), 23 deletions(-)

diff --git a/src/contact_search.jl b/src/contact_search.jl @@ -124,8 +124,7 @@ function checkAndAddContact!(sim::Simulation, i::Int, j::Int) if i < j if (sim.ice_floes[i].fixed && sim.ice_floes[j].fixed) || - !sim.ice_floes[i].enabled || - !sim.ice_floes[j].enabled + !sim.ice_floes[i].enabled || !sim.ice_floes[j].enabled return end @@ -140,16 +139,18 @@ function checkAndAddContact!(sim::Simulation, i::Int, j::Int) error("contact $i-$j exceeds max. number of contacts " * "(Nc_max = $Nc_max) for ice floe $i") - elseif sim.ice_floes[i].contacts[ic] == j - break # contact already registered - - elseif sim.ice_floes[i].contacts[ic] == 0 # empty - sim.ice_floes[i].n_contacts += 1 # register new contact - sim.ice_floes[j].n_contacts += 1 - sim.ice_floes[i].contacts[ic] = j - sim.ice_floes[i].contact_parallel_displacement[ic] = - zeros(2) - break + else + if sim.ice_floes[i].contacts[ic] == j + break # contact already registered + + elseif sim.ice_floes[i].contacts[ic] == 0 # empty + sim.ice_floes[i].n_contacts += 1 # register new contact + sim.ice_floes[j].n_contacts += 1 + sim.ice_floes[i].contacts[ic] = j + sim.ice_floes[i].contact_parallel_displacement[ic] = + zeros(2) + break + end end end end diff --git a/src/icefloe.jl b/src/icefloe.jl @@ -261,6 +261,51 @@ function convertIceFloeDataToArrays(simulation::Simulation) return ifarr end +export printIceFloeInfo +""" + printIceFloeInfo(icefloe::IceFloeCylindrical) + +Prints the contents of an ice floe to stdout in a formatted style. +""" +function printIceFloeInfo(f::IceFloeCylindrical) + println(" density: $(f.density) kg/m^3") + println(" thickness: $(f.thickness) m") + println(" contact_radius: $(f.contact_radius) m") + println(" areal_radius: $(f.areal_radius) m") + println(" circumreference: $(f.circumreference) m") + println(" horizontal_surface_area: $(f.horizontal_surface_area) m^2") + println(" side_surface_area: $(f.side_surface_area) m^2") + println(" volume: $(f.volume) m^3") + println(" mass: $(f.mass) kg") + println(" moment_of_inertia: $(f.moment_of_inertia) kg*m^2\n") + + println(" lin_pos: $(f.lin_pos) m") + println(" lin_vel: $(f.lin_vel) m/s") + println(" lin_acc: $(f.lin_acc) m/s^2") + println(" force: $(f.force) N\n") + + println(" ang_pos: $(f.ang_pos) rad") + println(" ang_vel: $(f.ang_vel) rad/s") + println(" ang_acc: $(f.ang_acc) rad/s^2") + println(" torque: $(f.torque) N*m\n") + + println(" fixed: $(f.fixed)") + println(" rotating: $(f.rotating)") + println(" enabled: $(f.enabled)\n") + + println(" k_n: $(f.contact_stiffness_normal) N/m") + println(" k_t: $(f.contact_stiffness_tangential) N/m") + println(" gamma_n: $(f.contact_viscosity_normal) N/(m/s)") + println(" gamma_t: $(f.contact_viscosity_tangential) N/(m/s)") + println(" mu_s: $(f.contact_static_friction)") + println(" mu_d: $(f.contact_dynamic_friction)\n") + + println(" pressure: $(f.pressure) Pa") + println(" n_contacts: $(f.n_contacts)") + println(" contacts: $(f.contacts)") + println(" delta_t: $(f.contact_parallel_displacement)") +end + export iceFloeKineticTranslationalEnergy "Returns the translational kinetic energy of the ice floe" function iceFloeKineticTranslationalEnergy(icefloe::IceFloeCylindrical) diff --git a/src/interaction.jl b/src/interaction.jl @@ -7,13 +7,13 @@ export interact! Resolve mechanical interaction between all particle pairs. """ function interact!(simulation::Simulation) - for i=1:Int(ceil(length(simulation.ice_floes)/2.)) # i <= Int(N/2) + for i=1:length(simulation.ice_floes) for ic=1:Nc_max j = simulation.ice_floes[i].contacts[ic] - if j == 0 - break # end of contact list reached + if i > j # skip i > j and j == 0 + continue end if norm(simulation.ice_floes[i].lin_pos - @@ -52,7 +52,10 @@ function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) # Floe distance delta_n = dist - (r_i + r_j) - if delta_n < 0. # Contact (this should always occur) + if delta_n > 0. # Double-check contact + error("function called to process non-existent contact between ice " * + "floes $i and $j") + else # Local axes n = p/dist @@ -128,8 +131,7 @@ function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) elseif k_t_harmonic_mean > 0. - force_t = -k_t_harmonic_mean*delta_t - - gamma_t_harmonic_mean*vel_t + 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) @@ -141,10 +143,6 @@ function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) error("unknown contact_tangential_rheology (k_t = " * "$k_t_harmonic_mean, gamma_t = $gamma_t_harmonic_mean") end - - else - error("function called to process non-existent contact between ice " * - "floes $i and $j") end simulation.ice_floes[i].contact_parallel_displacement[ic] = delta_t*t diff --git a/test/collision-5floes-normal.jl b/test/collision-5floes-normal.jl @@ -39,6 +39,11 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test_approx_eq_eps E_kin_lin_init E_kin_lin_final E_kin_lin_init*tol @test_approx_eq E_kin_rot_init E_kin_rot_final +@test 0. < norm(sim.ice_floes[1].lin_vel) +for i=2:5 + info("testing ice floe $i") + @test 0. ≈ norm(sim.ice_floes[i].lin_vel) +end info("Testing kinetic energy conservation with Two-term Taylor scheme") @@ -52,6 +57,11 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test_approx_eq_eps E_kin_lin_init E_kin_lin_final E_kin_lin_init*tol @test_approx_eq E_kin_rot_init E_kin_rot_final +@test 0. < norm(sim.ice_floes[1].lin_vel) +for i=2:5 + info("testing ice floe $i") + @test 0. ≈ norm(sim.ice_floes[i].lin_vel) +end info("Testing kinetic energy conservation with Three-term Taylor scheme") @@ -66,6 +76,11 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test_approx_eq_eps E_kin_lin_init E_kin_lin_final E_kin_lin_init*tol @test_approx_eq E_kin_rot_init E_kin_rot_final +@test 0. < norm(sim.ice_floes[1].lin_vel) +for i=2:5 + info("testing ice floe $i") + @test 0. ≈ norm(sim.ice_floes[i].lin_vel) +end info("# Ice floes free to move") @@ -84,7 +99,7 @@ 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) +SeaIce.setTotalTime!(sim, 40.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") @@ -97,6 +112,10 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test_approx_eq_eps E_kin_lin_init E_kin_lin_final E_kin_lin_init*tol @test_approx_eq E_kin_rot_init E_kin_rot_final +for i=1:5 + info("testing ice floe $i") + @test 0. < norm(sim.ice_floes[i].lin_vel) +end info("Testing kinetic energy conservation with Two-term Taylor scheme") @@ -110,6 +129,10 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test_approx_eq_eps E_kin_lin_init E_kin_lin_final E_kin_lin_init*tol @test_approx_eq E_kin_rot_init E_kin_rot_final +for i=1:5 + info("testing ice floe $i") + @test 0. < norm(sim.ice_floes[i].lin_vel) +end info("Testing kinetic energy conservation with Three-term Taylor scheme") @@ -124,6 +147,10 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test_approx_eq_eps E_kin_lin_init E_kin_lin_final E_kin_lin_init*tol @test_approx_eq E_kin_rot_init E_kin_rot_final +for i=1:5 + info("testing ice floe $i") + @test 0. < norm(sim.ice_floes[i].lin_vel) +end info("# Adding contact-normal viscosity") @@ -166,6 +193,11 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test_approx_eq E_kin_rot_init E_kin_rot_final +@test 0. < norm(sim.ice_floes[1].lin_vel) +for i=2:5 + info("testing ice floe $i") + @test 0. ≈ norm(sim.ice_floes[i].lin_vel) +end info("Testing kinetic energy conservation with Three-term Taylor scheme") @@ -180,6 +212,11 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test_approx_eq E_kin_rot_init E_kin_rot_final +@test 0. < norm(sim.ice_floes[1].lin_vel) +for i=2:5 + info("testing ice floe $i") + @test 0. ≈ norm(sim.ice_floes[i].lin_vel) +end info("# Ice floes free to move") @@ -217,6 +254,10 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test_approx_eq E_kin_rot_init E_kin_rot_final +for i=1:5 + info("testing ice floe $i") + @test 0. < norm(sim.ice_floes[i].lin_vel) +end info("Testing kinetic energy conservation with Three-term Taylor scheme") @@ -231,3 +272,7 @@ E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test_approx_eq E_kin_rot_init E_kin_rot_final +for i=1:5 + info("testing ice floe $i") + @test 0. < norm(sim.ice_floes[i].lin_vel) +end