Granular.jl

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

commit ccd9921a7fd354df82bcfcfb115844cc26278beb
parent a9d41bf6abc198818ed79d3ff76f9be05bd9a80b
Author: Anders Damsgaard <andersd@riseup.net>
Date:   Tue, 14 Nov 2017 14:58:58 -0500

fix various errors during test and wall initialization

Diffstat:
Mdocs/src/man/getting_started.md | 4++--
Msrc/simulation.jl | 4++--
Msrc/wall.jl | 61++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mtest/memory-management.jl | 4++--
Mtest/wall.jl | 20++++++++++++++++++--
5 files changed, 82 insertions(+), 11 deletions(-)

diff --git a/docs/src/man/getting_started.md b/docs/src/man/getting_started.md @@ -16,14 +16,14 @@ The relevant functions are all contained in the `Granular` module, which can be imported with `import Granular`. *Note:* As per Julia conventions, functions that contain an exclamation mark (!) modify the values of the arguments. -Any of the functions called below are documented in the source code, and their +All of the functions called below are documented in the source code, and their documentation can be found in the [Public API Index](@ref main-index) in the online documentation, or simply from the Julia shell by typing `?<function name>`. An example: ```julia-repl julia> ?Granular.createSimulation - createSimulation([id::String="unnamed"]) + createSimulation([id]) Create a simulation object to contain all relevant variables such as temporal parameters, fluid grids, grains, and contacts. The parameter id is used to diff --git a/src/simulation.jl b/src/simulation.jl @@ -2,7 +2,7 @@ export createSimulation """ - createSimulation([id::String="unnamed"]) + createSimulation([id]) Create a simulation object to contain all relevant variables such as temporal parameters, fluid grids, grains, and contacts. The parameter `id` is used to @@ -227,7 +227,7 @@ Add an `wall` to the `simulation` object. If `verbose` is true, a short confirmation message will be printed to stdout. """ function addWall!(simulation::Simulation, - grain::WallLinearFrictionless, + wall::WallLinearFrictionless, verbose::Bool = false) push!(simulation.walls, wall) diff --git a/src/wall.jl b/src/wall.jl @@ -87,7 +87,7 @@ function addWallLinearFrictionless!(simulation::Simulation, # if not set, set wall mass to equal the mass of all grains. if isnan(mass) - if length(simulation.grains < 1) + if length(simulation.grains) < 1 error("If wall mass is not specified, walls should be added " * "after grains have been added to the simulation.") end @@ -100,13 +100,13 @@ function addWallLinearFrictionless!(simulation::Simulation, # if not set, set wall thickness to equal largest grain thickness if isnan(thickness) - if length(simulation.grains < 1) + if length(simulation.grains) < 1 error("If wall thickness is not specified, walls should be added " * "after grains have been added to the simulation.") end thickness = -Inf for grain in simulation.grains - if grain.thickess > thickness + if grain.thickness > thickness thickness = grain.thickness end end @@ -128,3 +128,58 @@ function addWallLinearFrictionless!(simulation::Simulation, nothing end +export getWallSurfaceArea +""" + getWallSurfaceArea(simulation, wall_index) + +Returns the surface area of the wall given the grid size and its index. + +# Arguments +* `simulation::Simulation`: the simulation object containing the wall. +* `wall_index::Integer=1`: the wall number in the simulation object. +""" +function getWallSurfaceArea(sim::Simulation, wall_index::Integer) + + if sim.walls[wall_index].normal ≈ [1., 0.] + return (sim.ocean.yq[end,end] - sim.ocean.yq[1,1]) * + sim.walls[wall_index].thickness + elseif sim.walls[wall_index].normal ≈ [0., 1.] + return (sim.ocean.xq[end,end] - sim.ocean.xq[1,1]) * + sim.walls[wall_index].thickness + else + error("Wall normal not understood") + end + nothing +end + +export getWallNormalStress +""" + getWallNormalStress(simulation[, wall_index, stress_type]) + +Returns the current "effective" or "defined" normal stress on the wall with +index `wall_index` inside the `simulation` object. The returned value is given +in Pascal. + +# Arguments +* `simulation::Simulation`: the simulation object containing the wall. +* `wall_index::Integer=1`: the wall number in the simulation object. +* `stress_type::String="effective"`: the normal-stress type to return. The + defined value corresponds to the normal stress that the wall is asked to + uphold. The effective value is the actual current normal stress. Usually, + the magnitude of the effective normal stress fluctuates around the defined + normal stress. +""" +function getWallNormalStress(sim::Simulation; + wall_index::Integer=1, + stress_type::String="effective") + if stress_type == "defined" + return sim.walls[wall_index].normal_stress + + elseif stress_type == "effective" + return sim.walls[wall_index].force / getWallSurfaceArea(sim, wall_index, + sim.ocean) + else + error("stress_type not understood, should be 'effective' or 'defined'" * + " but is '$stress_type'.") + end +end diff --git a/test/memory-management.jl b/test/memory-management.jl @@ -5,8 +5,8 @@ info("#### $(basename(@__FILE__)) ####") info("Testing memory footprint of Granular types") sim = Granular.createSimulation() -empty_sim_size = 96 -empty_sim_size_recursive = 544 +empty_sim_size = 104 +empty_sim_size_recursive = 552 @test sizeof(sim) == empty_sim_size @test Base.summarysize(sim) == empty_sim_size_recursive diff --git a/test/wall.jl b/test/wall.jl @@ -28,6 +28,22 @@ Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 2., verbose=false) sim.grains[1].mass = 1.0 Granular.addWallLinearFrictionless!(sim, [1., 0.], 1., verbose=true) @test length(sim.walls) == 1 -@test sim.walls.mass ≈ 1.0 -@test sim.walls.mass ≈ 2.0 +@test sim.walls[1].mass ≈ 1.0 +@test sim.walls[1].thickness ≈ 2.0 + +info("Test wall surface area and defined normal stress") +sim = Granular.createSimulation(id="test") +sim.ocean = Granular.createRegularOceanGrid([1, 1, 1], [10., 20., 1.0]) +Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 2., verbose=false) +sim.grains[1].mass = 1.0 +Granular.addWallLinearFrictionless!(sim, [1., 0.], 1., verbose=true) +Granular.addWallLinearFrictionless!(sim, [0., 1.], 1., verbose=true) +@test length(sim.walls) == 2 +@test sim.walls[1].mass ≈ 1.0 +@test sim.walls[1].thickness ≈ 2.0 +@test sim.walls[2].mass ≈ 1.0 +@test sim.walls[2].thickness ≈ 2.0 +@test Granular.getWallSurfaceArea(sim, 1) ≈ 20.0*2.0 +@test Granular.getWallSurfaceArea(sim, 2) ≈ 10.0*2.0 +