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:
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)
+