Granular.jl

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

commit bcc9daa32ee17a31b2576133f546cb19890c539e
parent f7da3ebd8db4dbfa61ca5c0ae22391cff43e8644
Author: Anders Damsgaard <andersd@riseup.net>
Date:   Wed, 24 Jan 2018 11:03:42 -0500

Add function to produce rasterized map of grain coverage

Diffstat:
Msrc/packing.jl | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/packing.jl | 43+++++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/src/packing.jl b/src/packing.jl @@ -307,3 +307,68 @@ function irregularPacking!(simulation::Simulation; info("Generated $(length(simulation.grains) - np_init) points") end end + +""" + rasterMap(sim, dx) + +Returns a rasterized map of grain extent in the domain with length `L` and a +pixel size of `dx`. The function will return a map of `Bool` type with size +`floor.(L./dx)`. + +* Arguments +- `sim::Simulation`: simulation object containing the grains. +- `dx::Real`: pixel size to use for the raster map. + +""" +function rasterMap(sim::Simulation, dx::Real) + + # Use existing `grid` (ocean or atmosphere) for contact search + if typeof(sim.ocean.input_file) != Bool + grid = sim.ocean + elseif typeof(sim.atmosphere.input_file) != Bool + grid = sim.atmosphere + else + error("rasterMap(...) requires an ocean or atmosphere grid") + end + # save grid boundaries + if grid.regular_grid + L = grid.L[1:2] + origo = grid.origo + else + sw, se, ne, nw = getGridCornerCoordinates(grid.xq, grid.yq) + L = [se[1] - sw[1], nw[2] - sw[2]] + origo = [sw[1], sw[2]] + end + const dims = floor.(L./dx) + occupied = zeros(Bool, dims[1], dims[2]) + + # Loop over existing grains and mark their extent in the `occupied` array + i = 0; j = 0 + min_i = 0; min_j = 0 + max_i = 0; max_j = 0 + cell_mid_point = zeros(2) + for grain in sim.grains + + # Find center position in `occupied` grid + #i, j = Int.(floor.((grain.lin_pos - origo) ./ dx)) + [1,1] + + # Find corner indexes for box spanning the grain + min_i, min_j = Int.(floor.((grain.lin_pos - origo - + grain.contact_radius) ./ dx)) + [1,1] + max_i, max_j = Int.(floor.((grain.lin_pos - origo + + grain.contact_radius) ./ dx)) + [1,1] + + # For each cell in box, check if the grain is contained + for i = min_i:max_i + for j = min_j:max_j + cell_mid_point = dx .* Vector{Float64}([i,j]) - 0.5 * dx + + if (norm(cell_mid_point - grain.lin_pos) - + grain.contact_radius < 0.5*dx) + occupied[i,j] = true + end + end + end + end + return occupied +end diff --git a/test/packing.jl b/test/packing.jl @@ -82,3 +82,46 @@ Granular.irregularPacking!(sim, plot_during_packing=plot_packings, verbose=verbose) @test length(sim.grains) > 280 + + +info("Testing raster-based packing algorithm") +sim = Granular.createSimulation("raster-packing1") +sim.ocean = Granular.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) +Granular.addGrainCylindrical!(sim, [0.5, 0.5], 0.4, 1.0) +occupied = Granular.rasterMap(sim, 0.08) +occupied_ans = Array{Bool}([ +0 0 0 0 0 0 0 0 0 0 0 0; +0 0 0 1 1 1 1 1 1 0 0 0; +0 0 1 1 1 1 1 1 1 1 0 0; +0 1 1 1 1 1 1 1 1 1 1 0; +0 1 1 1 1 1 1 1 1 1 1 0; +0 1 1 1 1 1 1 1 1 1 1 1; +0 1 1 1 1 1 1 1 1 1 1 1; +0 1 1 1 1 1 1 1 1 1 1 1; +0 1 1 1 1 1 1 1 1 1 1 0; +0 0 1 1 1 1 1 1 1 1 1 0; +0 0 0 1 1 1 1 1 1 1 0 0; +0 0 0 0 0 1 1 1 0 0 0 0]) +@test occupied == occupied_ans +Granular.addGrainCylindrical!(sim, [0.03, 0.03], 0.02, 1.0) +occupied = Granular.rasterMap(sim, 0.08) +occupied_ans = Array{Bool}([ +1 0 0 0 0 0 0 0 0 0 0 0; +0 0 0 1 1 1 1 1 1 0 0 0; +0 0 1 1 1 1 1 1 1 1 0 0; +0 1 1 1 1 1 1 1 1 1 1 0; +0 1 1 1 1 1 1 1 1 1 1 0; +0 1 1 1 1 1 1 1 1 1 1 1; +0 1 1 1 1 1 1 1 1 1 1 1; +0 1 1 1 1 1 1 1 1 1 1 1; +0 1 1 1 1 1 1 1 1 1 1 0; +0 0 1 1 1 1 1 1 1 1 1 0; +0 0 0 1 1 1 1 1 1 1 0 0; +0 0 0 0 0 1 1 1 0 0 0 0]) +@test occupied == occupied_ans + +#Granular.rasterPacking!(sim, + #radius_max=.01, + #radius_min=.01, + #verbose=verbose) +