tadjust grain linear positions according to boundary periodicity - 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 2f86b2f3bb054dd34b2ea35c1a65ebe455b15646
 (DIR) parent 6040ef7fcf67910a07df699fe383a365fde93796
 (HTM) Author: Anders Damsgaard <andersd@riseup.net>
       Date:   Fri,  3 Nov 2017 16:13:59 -0400
       
       adjust grain linear positions according to boundary periodicity
       
       Diffstat:
         M src/grid.jl                         |      60 +++++++++++++++++++++++++++++++
         M src/temporal_integration.jl         |       7 +++++--
         M test/periodic-boundaries.jl         |      66 +++++++++++++++++++++++++++++++
       
       3 files changed, 131 insertions(+), 2 deletions(-)
       ---
 (DIR) diff --git a/src/grid.jl b/src/grid.jl
       t@@ -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
 (DIR) diff --git a/src/temporal_integration.jl b/src/temporal_integration.jl
       t@@ -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 
       t@@ -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
       t@@ -36,6 +38,7 @@ function updateGrainKinematics!(simulation::Simulation;
            else
                error("Unknown integration method '$method'")
            end
       +    moveGrainsAcrossPeriodicBoundaries!(simulation)
            nothing
        end
        
 (DIR) diff --git a/test/periodic-boundaries.jl b/test/periodic-boundaries.jl
       t@@ -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)
       +