Granular.jl

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

commit 2f86b2f3bb054dd34b2ea35c1a65ebe455b15646
parent 6040ef7fcf67910a07df699fe383a365fde93796
Author: Anders Damsgaard <andersd@riseup.net>
Date:   Fri,  3 Nov 2017 16:13:59 -0400

adjust grain linear positions according to boundary periodicity

Diffstat:
Msrc/grid.jl | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/temporal_integration.jl | 7+++++--
Mtest/periodic-boundaries.jl | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 131 insertions(+), 2 deletions(-)

diff --git a/src/grid.jl b/src/grid.jl @@ -732,3 +732,63 @@ function reportGridBoundaryConditions(grid::Any) "\t($(grid.bc_north))") nothing end + +""" + moveGrainsAcrossPeriodicBoundaries!(simulation::Simulation) + +If the ocean or atmosphere grids are periodic, move grains that are placed +outside the domain correspondingly across the domain. This function is to be +called after temporal integration of the grain positions. +""" +function moveGrainsAcrossPeriodicBoundaries!(sim::Simulation) + + + # return if grids are not enabled + if typeof(sim.ocean.input_file) == Bool && + typeof(sim.atmosphere.input_file) == Bool + return nothing + end + + # return immediately if no boundaries are periodic + if sim.ocean.bc_west != 2 && + sim.ocean.bc_south != 2 && + sim.ocean.bc_east != 2 && + sim.ocean.bc_north != 2 + return nothing + end + + # throw error if ocean and atmosphere grid BCs are different and both are + # enabled + if (typeof(sim.ocean.input_file) != Bool && + typeof(sim.atmosphere.input_file) != Bool) && + (sim.ocean.bc_west != sim.atmosphere.bc_west && + sim.ocean.bc_south != sim.atmosphere.bc_south && + sim.ocean.bc_east != sim.atmosphere.bc_east && + sim.ocean.bc_north != sim.atmosphere.bc_north) + error("Ocean and Atmosphere grid boundary conditions differ") + end + + for grain in sim.grains + + # -x -> +x + if sim.ocean.bc_west == 2 && grain.lin_pos[1] < sim.ocean.xq[1] + grain.lin_pos[1] += sim.ocean.xq[end] - sim.ocean.xq[1] + end + + # -y -> +y + if sim.ocean.bc_south == 2 && grain.lin_pos[2] < sim.ocean.yq[1] + grain.lin_pos[2] += sim.ocean.yq[end] - sim.ocean.yq[1] + end + + # +x -> -x + if sim.ocean.bc_east == 2 && grain.lin_pos[1] > sim.ocean.xq[end] + grain.lin_pos[1] -= sim.ocean.xq[end] - sim.ocean.xq[1] + end + + # +y -> -y + if sim.ocean.bc_east == 2 && grain.lin_pos[2] > sim.ocean.yq[end] + grain.lin_pos[2] -= sim.ocean.yq[end] - sim.ocean.yq[1] + end + end + nothing +end diff --git a/src/temporal_integration.jl b/src/temporal_integration.jl @@ -4,7 +4,9 @@ export updateGrainKinematics! method::String = "Three-term Taylor"]) Update the grain kinematic parameters using a temporal integration scheme, -the current force and torque balance, and gravitational acceleration. +the current force and torque balance, and gravitational acceleration. If the +simulation contains a grid with periodic boundaries, affected grain positions +are adjusted accordingly. # Arguments * `simulation::Simulation`: update the grain positions in this object @@ -17,7 +19,7 @@ the current force and torque balance, and gravitational acceleration. precision if the time step is 1/10 the length. """ function updateGrainKinematics!(simulation::Simulation; - method::String = "Three-term Taylor") + method::String = "Three-term Taylor") if method == "Two-term Taylor" for grain in simulation.grains @@ -36,6 +38,7 @@ function updateGrainKinematics!(simulation::Simulation; else error("Unknown integration method '$method'") end + moveGrainsAcrossPeriodicBoundaries!(simulation) nothing end diff --git a/test/periodic-boundaries.jl b/test/periodic-boundaries.jl @@ -122,3 +122,69 @@ Test.@test 2 == sim.grains[1].contacts[1] Test.@test 1 == sim.grains[1].n_contacts Test.@test 1 == sim.grains[2].n_contacts + +info("Test grain position adjustment across periodic boundaries") +# do not readjust inside grid, inactive boundaries +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([5, 5, 2], [1., 1., 1.]) +Granular.setGridBoundaryConditions!(sim.ocean, "inactive", verbose=false) +Granular.addGrainCylindrical!(sim, [0.1, 0.5], 0.11, 0.1, verbose=false) +Granular.moveGrainsAcrossPeriodicBoundaries!(sim) +Test.@test [0.1, 0.5] ≈ sim.grains[1].lin_pos + +# do not readjust inside grid, periodic boundaries +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([5, 5, 2], [1., 1., 1.]) +Granular.setGridBoundaryConditions!(sim.ocean, "periodic", verbose=false) +Granular.addGrainCylindrical!(sim, [0.1, 0.5], 0.11, 0.1, verbose=false) +Granular.moveGrainsAcrossPeriodicBoundaries!(sim) +Test.@test [0.1, 0.5] ≈ sim.grains[1].lin_pos + +# do not readjust outside grid, inactive boundaries +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([5, 5, 2], [1., 1., 1.]) +Granular.setGridBoundaryConditions!(sim.ocean, "inactive", verbose=false) +Granular.addGrainCylindrical!(sim, [-0.1, 0.5], 0.11, 0.1, verbose=false) +Granular.moveGrainsAcrossPeriodicBoundaries!(sim) +Test.@test [-0.1, 0.5] ≈ sim.grains[1].lin_pos + +# readjust outside grid, periodic boundaries, -x +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([5, 5, 2], [1., 1., 1.]) +Granular.setGridBoundaryConditions!(sim.ocean, "periodic", verbose=false) +Granular.addGrainCylindrical!(sim, [-0.1, 0.5], 0.11, 0.1, verbose=false) +Granular.moveGrainsAcrossPeriodicBoundaries!(sim) +Test.@test [0.9, 0.5] ≈ sim.grains[1].lin_pos + +# readjust outside grid, periodic boundaries, +x +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([5, 5, 2], [1., 1., 1.]) +Granular.setGridBoundaryConditions!(sim.ocean, "periodic", verbose=false) +Granular.addGrainCylindrical!(sim, [1.1, 0.5], 0.11, 0.1, verbose=false) +Granular.moveGrainsAcrossPeriodicBoundaries!(sim) +Test.@test [0.1, 0.5] ≈ sim.grains[1].lin_pos + +# readjust outside grid, periodic boundaries, -y +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([5, 5, 2], [1., 1., 1.]) +Granular.setGridBoundaryConditions!(sim.ocean, "periodic", verbose=false) +Granular.addGrainCylindrical!(sim, [0.3, -0.1], 0.11, 0.1, verbose=false) +Granular.moveGrainsAcrossPeriodicBoundaries!(sim) +Test.@test [0.3, 0.9] ≈ sim.grains[1].lin_pos + +# readjust outside grid, periodic boundaries, +y +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([5, 5, 2], [1., 1., 1.]) +Granular.setGridBoundaryConditions!(sim.ocean, "periodic", verbose=false) +Granular.addGrainCylindrical!(sim, [0.3, 1.1], 0.11, 0.1, verbose=false) +Granular.moveGrainsAcrossPeriodicBoundaries!(sim) +Test.@test [0.3, 0.1] ≈ sim.grains[1].lin_pos + +# throw error if atmosphere and ocean BCs differ +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([5, 5, 2], [1., 1., 1.]) +sim.atmosphere = Granular.createRegularAtmosphereGrid([5, 5, 2], [1., 1., 1.]) +Granular.setGridBoundaryConditions!(sim.ocean, "periodic", verbose=false) +Granular.addGrainCylindrical!(sim, [0.3, 1.1], 0.11, 0.1, verbose=false) +Test.@test_throws ErrorException Granular.moveGrainsAcrossPeriodicBoundaries!(sim) +